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

Reply via email to