On Mon, Oct 28, 2013 at 12:15 PM, Richard Smith <[email protected]>wrote:
> On Sat, Oct 26, 2013 at 10:14 AM, Argyrios Kyrtzidis <[email protected]>wrote: > >> As I said above, I think there's a misunderstanding here; to reiterate: >> when you say "I want to use the interface provided by M1. If I've not >> imported M2" this is case 1) I mentioned and I agree with what you said >> should happen. If this does not happen currently then it should be fixed. >> >> Should we focus on what should happen when importing *both* M1 and M2 ? >> > > Yes, I think refocusing will help. In particular, I think this is the key > question on which we have different views: > > >> How do I know that two modules are *related* ? One module may have >> imported the other but if it doesn't re-export it it might as well be an >> *unrelated* one from my perspective; why do I need to care what modules it >> imported internally ? >> > > There are (I think) two different ways that two modules can have a > conflict on what a macro name means: > > 1) Both modules want the name to mean something (which be mean "it's a > macro expanding to X" or might be "it's not a macro"). > 2) One module wants to *override* what another module meant the name to > mean (M2 says "it expands to FOO BAR", and M1 says "actually, I override M2 > and say it expands to BAZ") > > There are also two different ways that a module can express its intent for > a macro name to mean something: > > A) It can #define the name to something > B) It can #undef the name > > I think we agree that: > > 1A: If two modules want the same macro name to be defined to different > things, and that macro name is used, that is clearly ambiguous and should > be diagnosed. > > I'm on the fence about this one: > > 1B: If one module wants the macro name to be #defined to something, and > another module wants it to be undefined, currently Clang silently picks the > definition. I am not entirely convinced that's appropriate -- if my module > explicitly #undef's a macro, that's a statement of intent: in my interface, > I'm using that name to mean something that's not a macro. I don't think > it's obvious that: > > #undef X > #define X X > > and > > #undef X > > should mean fundamentally different things here. Either way, I'm saying "I > own the macro name X and it produces the token sequence X." > Hmm, I think it's actually rather important that we diagnose this: on the upgrade path from #includes to modules, we'll get a silent change of behavior without this. If we do diagnose this case (where two imported modules disagree on a macro: one says it should be defined and the other says it should not), then I care a lot less about case 2. (It's enough for me that we diagnose this; we don't need to preserve the existing behavior.) That said, I think we should take as a guiding rule that modules and submodules should behave the same, and we currently violate that in the case of macros. > Case 2 is where we really seem to disagree. It's also a weird case for > modules, since we rarely have cases in which the interface of one module > includes "modify the interface of another module". Which brings me to your > next point: > > >> I'm suggesting that If I explicitly import 2 modules, and the modules' >> interfaces disagree on what an identifier means, then there is ambiguity. >> One module may or may not have imported the other module internally, but >> that doesn't change the fact that the modules' interfaces disagree on the >> meaning of an identifier. >> > > The key thing for me is, if one module imports another module, undefines > some part of it, then re-exports it, it seems pretty clear that it intends > to *modify* the interface of that first module. This happens in other > guises too: extending overload sets, specializing templates, shadowing a > tag name with a non-tag name, and so on. In all other cases, importing both > modules gives you the modified interface *with no ambiguity*. The ambiguity > has already been resolved by the dominating module saying how to resolve > it. And if I import a module that says that it modifies another module's > interface, I expect to get that modified interface. > > So: 2A) if M2 defines our macro, and M1 imports M2 and undefines and > redefines that macro, and either I import M1 or I import *both* M1 and M2, > I've expressed my intent to use M1's resolution to the conflict, and I > think I should get M1's definition. > 2B) if M2 defines our macro, and M1 imports M2 and undefines the macro, > and either I import M1 or I import both M1 and M2, I think the macro should > not be defined. > > By exporting a macro undefinition that undefines M2's macro, M1 is saying > "importing me undefines M2's macro definition". There's no ambiguity in > that, and if I import both modules, that's what I expect to happen. This > would behave in (largely) the same way we behave across submodules in the > same module, which makes the intuitive model simpler. If M1 didn't want > this behavior, it should not export the macro. > > > Let me make my proposal a bit more concrete, since I think I've been vague > up until now. > > Instead of storing a single flat list of macro definitions and undefines, > we store a DAG. The predecessors of each directive are the set of > directives that were visible at the point of the directive. (For a #define, > these must all be either #undefs or #defines to the same value.) When we > see a macro name being used, we take the set of visible leaves of this > graph, check they are consistent[1], and use that consistent value as the > value of the macro. Otherwise, we diagnose. > > [1] I'm not certain whether consistency should allow a mixture of #undefs > and #defines, but I'm inclined to think it should not. >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
