<div dir="ltr">Looks like <a href="https://reviews.llvm.org/D122766">https://reviews.llvm.org/D122766</a> (-ffile-reproducible) might solve my immediate issues in clang, but I think we should still consider moving to a more canonical naming of lambdas that, necessarily, doesn't include the file name (unfortunately). Probably has to include the lambda numbering/something roughly equivalent to the mangled lambda name - it could include type information (it'd be superfluous to a unique identifier, but I don't think it would break consistently naming the same type across CUs either).<br><br>Anyone got ideas/preferences/thoughts on this?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jan 24, 2022 at 5:51 PM David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Mon, Jan 24, 2022 at 5:37 PM Adrian Prantl <<a href="mailto:aprantl@apple.com" target="_blank">aprantl@apple.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><br><div><br><blockquote type="cite"><div>On Jan 23, 2022, at 2:53 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>> wrote:</div><br><div><div dir="ltr">A rather common "quality of implementation" issue seems to be lambda naming.<br><br>I came across this due to non-canonicalization of lambda names in template parameters depending on how a source file is named in Clang, and GCC's seem to be very ambiguous:<br><br><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">$ cat tmp/lambda.h</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">template<typename T></span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">void f1(T) { }</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">static int i = (f1([]{}), 1);</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">static int j = (f1([]{}), 2);</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">void f1() {</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>  </span>f1([]{});</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>  </span>f1([]{});</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(57,192,38)"><span style="font-variant-ligatures:no-common-ligatures">$ cat tmp/lambda.cpp</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">#ifdef I_PATH</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">#include <tmp/lambda.h></span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">#else</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">#include "lambda.h"</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">#endif</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">$ clang++-tot tmp/lambda.cpp -g -c -I. -DI_PATH && llvm-dwarfdump-tot lambda.o | grep "f1<"</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at ./tmp/lambda.h:3:20)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at ./tmp/lambda.h:4:20)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at ./tmp/lambda.h:6:6)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at ./tmp/lambda.h:7:6)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">$ clang++-tot tmp/lambda.cpp -g -c && llvm-dwarfdump-tot lambda.o | grep "f1<"</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at tmp/lambda.h:3:20)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at tmp/lambda.h:4:20)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at tmp/lambda.h:6:6)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">(lambda at tmp/lambda.h:7:6)>")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">$ g++-tot tmp/lambda.cpp -g -c -I. && llvm-dwarfdump-tot lambda.o | grep "f1<"</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">f1()::<lambda()> >")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures">f1()::<lambda()> >")</span></div><div style="margin:0px;font-style:normal;font-variant-caps:normal;font-weight:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures"><lambda()> >")</span></div><p style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo">


































</p><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span>DW_AT_name<span>      </span>("</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(202,51,35)"><b>f1<</b></span><span style="font-variant-ligatures:no-common-ligatures"><lambda()> >")</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">



<br></span></div>(I came across this in the context of my simplified template names work - rebuilding names from the DW_TAG description of the template parameters - and while I'm not rebuilding names that have lambda parameters (keep encoding the full string instead). The issue is if some other type depending on a type with a lambda parameter - but then multiple uses of that inner type exist, from different translation units (using type units) with different ways of naming the same file - so then the expected name has one spelling, but the actual spelling is different due to the "./")<br><br>But all this said - it'd be good to figure out a reliable naming - the naming we have here, while usable for humans (pointing to surce files, etc) - they don't reliably give unique names for each lambda/template instantiation which would make it difficult for a consumer to know if two entities are the same (important for types - is some function parameter the same type as another type?)<br><br>While it's expected cross-producer (eg: trying to be compatible with GCC and Clang debug info) you have to do some fuzzy matching (eg: "f1<int*>" or "f1<int *>" at the most basic - there are more complicated cases) - this one's not possible with the data available.<br><br>The source file/line/column is insufficient to uniquely identify a lambda (multiple lambdas stamped out by a macro would get all the same file/line/col) and valid code (albeit unlikely) that writes the same definition in multiple places could make the same lambda have different names.<br><br>We should probably use something more like the way various ABI manglings do to identify these entities.<br><br>But we should probably also do this for other unnamed types that have linkage (need to/would benefit from being matched up between two CUs), even not lambdas.<br><br>FWIW, at least the llvm-cxxfilt demanglings of clang's manglings for these symbols is:<br><br><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span> </span>void f1<$_0>($_0)</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> f1<$_1>($_1)</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> void f1<f1()::$_2>(f1()::$_2)</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> void f1<f1()::$_3>(f1()::$_3)</span></div><br>Should we use that instead?<br></div></div></blockquote><div><br></div><div>The only other information that the current human-readable DWARF name carries is the file+line and that is fully redundant with DW_AT_file/line, so the above scheme seem reasonable to me. Poorly symbolicated backtraces would be worse in this scheme, so I'm expecting most pushback from users who rely on a tool that just prints the human readable name with no source info.</div></div></div></blockquote><div><br>Yeah - you can always pull the file/line/col from the DW_AT_decl_* anyway, so encoding it in the type name does seem redundant and inefficient indeed (beyond/independent of the correctness issues).<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><blockquote type="cite"><div><div dir="ltr">GCC's mangling's different (in these examples that's OK, since they're all internal linkage):<br><br><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> void f1<f1()::'lambda0'()>(f1()::'lambda0'())</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> void f1<f1()::'lambda'()>(f1()::'lambda'())</span></div><br>If I add an example like this:<br><br>inline auto f1() { return []{}; }<br><br>and instantiate the template with the result of f1:<br><br><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> void f1<f2()::'lambda'()>(f2()::'lambda'())<br><br></span></div>





GCC:<br><br><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> void f1<f2()::'lambda'()>(f2()::'lambda'()) </span></div><br>So they consistently use the same mangling - we could use the same naming for template parameters?<br><br>How should we communicate this sort of identity for unnamed types in the DIEs describing the types themselves (not just the string of a template name of a type instantiated with the unnamed type) so the unnamed type can be matched up between translation units.<br><br>eg, if I have these two translation units:<br>// header<br>inline auto f1() { struct { } local; return local; }<br>// unit 1:<br>#include "header"<br>auto f2(decltype(f1())) { }<br>// unit 2:<br>#include "header"<br>decltype(f1()) v1;<br><br>Currently the DWARF produced for this unnamed type is:<br><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(86,32,244)"><span style="font-variant-ligatures:no-common-ligatures;color:rgb(170,171,37)">0x0000003f: </span><span style="font-variant-ligatures:no-common-ligatures"><span>  </span>DW_TAG_structure_type</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">DW_AT_calling_convention</span><span style="font-variant-ligatures:no-common-ligatures"><span>        </span>(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(219,39,218)">DW_CC_pass_by_value</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">DW_AT_byte_size</span><span style="font-variant-ligatures:no-common-ligatures"> (0x01)</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(57,192,38)"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">DW_AT_decl_file</span><span style="font-variant-ligatures:no-common-ligatures"> (</span><span style="font-variant-ligatures:no-common-ligatures">"/usr/local/google/home/blaikie/dev/scratch/test.cpp"</span><span style="font-variant-ligatures:no-common-ligatures">)</span></div><div style="margin:0px;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"><span>                </span></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(56,185,199)">DW_AT_decl_line</span><span style="font-variant-ligatures:no-common-ligatures"> (1)<br><br></span></div></div></div></blockquote><div><br></div><div>is this the type of struct {}?</div></div></div></blockquote><div><br>Yep. You'll get separate distinct descriptions that are essentially the same - imagine if `f1` had two such types written as "struct {}" (say they were used to instantiate two different templates - "struct {} a; struct {} b; f_templ(a); f_templ(b);" - the DWARF will have two of those unnamed DW_TAG_structure_types and two template specializations, etc - but no way to know which of those unnamed types line up with uses in another translation unit, in terms of overload resolution, etc.<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><blockquote type="cite"><div><div dir="ltr"><div>So there's no way to know if you see that structure type definition in two different translation units whether they refer to the same type because there may be multiple types that have the same DWARF description. (so no way to know if the DWARF consumer should allow the user to evaluate an expression `f2(v1)` or not, I think?)<br></div></div></div></blockquote><div><br></div><div>Does a C++ compiler usually treat structurally equivalent but differently named types as interchangeable?</div></div></div></blockquote><div><br>No - given "struct A { int i; }; struct B { int i; }; void f1(A); ... " - "f1(A())" is valid, but "f1(B())" is invalid and an error at compile-time. <a href="https://godbolt.org/z/de7Yce1qW" target="_blank">https://godbolt.org/z/de7Yce1qW</a><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><div>Does a C++ compiler usually treat structurally equivalent anonymous types as interchangeable?</div></div></div></blockquote><div><br>No, same rules apply as named types: <a href="https://godbolt.org/z/hxWMYbWc8" target="_blank">https://godbolt.org/z/hxWMYbWc8</a><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div><div><br></div><div>-- adrian</div><div><br></div><blockquote type="cite"><div><div dir="ltr"><div><br>I guess the only way to have an unnamed type with linkage is to use it inside an inline function - so within that scope you'd have to produce DWARF for any types consistently in all definitions of the function and then a consumer could match them up by counting (assuming the unnamed types were always emitted in the same order in the child DIE list)... <br><br>But this all seems a bit subtle & maybe would benefit from a more robust/explicit description? <br><br>Perhaps adding an integer attribute to number anonymous types? They'd need to differentiate between lambdas and other anonymous types, since they have separate numberings.</div></div>
</div></blockquote></div><br></div></blockquote></div></div>
</blockquote></div>