On Wed, Apr 1, 2020 at 2:55 PM Nathan Sidwell <nat...@acm.org> wrote:
> Jason, > > This is from pr94426, which is fallout from my pr94147 fix. > > You added the following to no_linkage_check as part of > > 2018-11-12 Jason Merrill <ja...@redhat.com> > Implement P0315R4, Lambdas in unevaluated contexts. > > /* Lambda types that don't have mangling scope have no linkage. We > check CLASSTYPE_LAMBDA_EXPR for error_mark_node because > when we get here from pushtag none of the lambda information is > set up yet, so we want to assume that the lambda has linkage and > fix it up later if not. We need to check this even in templates so > that we properly handle a lambda-expression in the signature. */ > if (LAMBDA_TYPE_P (t) > && CLASSTYPE_LAMBDA_EXPR (t) != error_mark_node > && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE) > return t; > > The comment suggests that those with a mangling scope do (sometimes?) > have linkage. Under what circumstances does the std give lambdas linkage? They are 'unique, unnamed non-union class type[s]' 7.5.5.1/1 > The wording in 6.3/14 suggests that even in: > inline auto var = []{}; > the multiple definitions of 'var' in different TUs could have different > types. > > 'In particular, lambda-expressions (7.5.5) appearing in the type of D > may result in the different declarations having distinct types,' > > so they can be ODR-same, but not TYPE-same. Comparing 'typeid (var)' > acrosss TU boundaries gives an unspecified result. > > I can see why implementationwise we might want the above to have a > pseudo-external linkage -- IIRC we don't correctly give templates > instantiated from non-external types internal linkage, so we have to > either guarantee unique mangling or guarantee same typeness. > We certainly work hard to do that; see constrain_visibility_for_template. > What am I missing? > A little before that we have "In each definition of D, except within the default arguments and default template arguments of D, corresponding lambda-expressions shall have the same closure type (see below)." So that's where the closure has "linkage". and then later we have "[Example: inline void f(bool cond, void (*p)()) { if (cond) f(false, []{}); } inline void g(bool cond, void (*p)() = []{}) { if (cond) g(false); } struct X { void h(bool cond, void (*p)() = []{}) { if (cond) h(false); } }; If the definition of f appears in multiple translation units, the behavior of the program is as if there is only one definition of f. If the definition of g appears in multiple translation units, the program is ill-formed (no diagnostic required) because each such definition uses a default argument that refers to a distinct lambda-expression closure type. The definition of X can appear in multiple translation units of a valid program; the lambda-expressions defined within the default argument of X::h within the definition of X denote the same closure type in each translation unit. — end example]" The reference to "type" in your quotation seems just wrong to me; if it's part of the type, it isn't from a default argument, so the closures have to be the same type. We should check that Davis' overhaul has a good answer for this. Jason