<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div><font face="monospace, monospace">Thanks again Richard for a second more detailed response setting</font><span style="font-family:monospace,monospace"> out the broader view</span><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">(I had failed to fully interpret /</font><span style="font-family:monospace,monospace"> misinterpreted</span><font face="monospace, monospace"> your first response</font><span style="font-family:monospace,monospace"> as mild pushback</span></div><div><span style="font-family:monospace,monospace"> apologies for that; I should've asked for the clarification)</span></div><div><span style="font-family:monospace,monospace">(also, I shouldn't have argued 'correctness' here; that was </span><font face="monospace, monospace">disingenuous).</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">So, in the broader view, the question is:</font></div><div><font face="monospace, monospace"> > How best to pretty print general non-type template args.</font></div><div><font face="monospace, monospace"><br></font></div><div><span style="font-family:monospace,monospace">Now, as non-types may be subsumed by LiteralType literals in C++20</span></div><div><span style="font-family:monospace,monospace">we should look ahead to pretty printing of such general literal types</span></div><div><span style="font-family:monospace,monospace">as the broader context for discussion or decisions on changes.</span></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">  Non-type template args<br>  Until C++17:<br></font><span style="font-family:monospace,monospace">    - an integral type;</span><br style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">    - an enumeration type;</span><br style="font-family:monospace,monospace"><font face="monospace, monospace">    - std::nullptr_t; (s</font><span style="font-family:monospace,monospace">ince C++11)</span><font face="monospace, monospace"><br>    - a pointer type (to object or to function);<br>    - a pointer to member type (to member object or to member function);<br></font><span style="font-family:monospace,monospace">    - lvalue reference type (to object or to function);</span></div><div><span style="font-family:monospace,monospace">  For C++20:</span></div><font face="monospace, monospace">    - A type that satisfies LiteralType, has strong structural equality ...</font></div><div dir="ltr"><br></div><div dir="ltr"><span style="font-family:monospace,monospace">Pretty-print design goals:</span><br></div><div><font face="monospace, monospace">  General: minimise special-casing</font></div><div><span style="font-family:monospace,monospace">  Round-trip: the printed value can be plugged back into code</span></div><div><font face="monospace, monospace">  Low-verbosity: avoid unnecessary info or repetition</font></div><div><font face="monospace, monospace">  more?</font></div><div><br></div><div><div dir="ltr"><font face="monospace, monospace">The general literal type can be one of the C++17 built-ins</font></div><div dir="ltr"><font face="monospace, monospace">as above </font><span style="font-family:monospace,monospace">(all scalar types, apart from lvalue reference I think)</span></div><div dir="ltr"><font face="monospace, monospace">or an aggregate or class that </font><span style="font-family:monospace,monospace">satisfies the LiteralType requirements.</span></div><div dir="ltr"><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">So, in general, we will now have to deal with</span><span style="font-family:monospace,monospace"> non-scalar types</span></div><div><div><span style="font-family:monospace,monospace">implying multiple initializers and init-lists.</span></div></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">Question: is there a single 'canonical' init-list for a LiteralType?</span></div></div><div dir="ltr"><br></div><div><font face="monospace, monospace">This is a place where the proposal to use parens for aggregates will help,</font></div><div><span style="font-family:monospace,monospace">as special-casing initialization syntax, for brace or paren, is awkward:</span><font face="monospace, monospace"><br></font></div><font face="monospace, monospace">P0960 Allow initializing aggregates from a parenthesized list of values</font><div><font face="monospace, monospace"><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0960r1.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0960r1.html</a></font><div><font face="monospace, monospace">If this proposal is accepted then that would suggest to prefer paren-init.</font></div></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">Literals of the existing types remain awkward non-types -</font></div><div><font face="monospace, monospace">'function-style' paren-init doesn't work directly for multi-token types</font></div><div><font face="monospace, monospace">(like 'long long') or for compound types (pointer/ref).</font></div><div><span style="font-family:monospace,monospace">An added decltype can solve that. </span><span style="font-family:monospace,monospace">Sticking with C-style cast is simpler.</span></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Here's a suggestion (assuming </font><span style="font-family:monospace,monospace">P0960 for non-scalars):</span></div><div><br></div><div><font face="monospace, monospace">  Scalar:</font></div><div><font face="monospace, monospace">    Known type T; print as 'value'</font></div><div><font face="monospace, monospace">    Deduced type; print as '(T)value'</font></div><div><font face="monospace, monospace">  Non-scalar:</font></div><div><font face="monospace, monospace">    Known type T; print as '(init...)'</font></div><div><font face="monospace, monospace">    Deduced type; print as 'T(init...)'</font></div><div><br></div><div><span style="font-family:monospace,monospace">'Known type' means non-deduced or T implicit in value</span><br></div><div><div><span style="font-family:monospace,monospace">(for </span><span style="font-family:monospace,monospace">values of scalar type like enumerator or pointer-to-member).</span></div></div><div><div><span style="font-family:monospace,monospace">(lvalue reference remains a special case).</span></div><br class="gmail-Apple-interchange-newline"></div><div><div><font face="monospace, monospace">In practice, I don't know if compilers can easily distinguish</font></div><div><font face="monospace, monospace">whether a value's type is known or deduced, at the leaf-level.</font></div><div><font face="monospace, monospace">If not then this change will be more involved than just updating</font></div><div><font face="monospace, monospace">low-level printing functions.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Now let's focus back on integral and enumeration types.</font></div><div><br></div><div><span style="font-family:monospace,monospace">Integral / enum types</span></div><div><font face="monospace, monospace">---------------------</font></div><div><font face="monospace, monospace">Clang, </font><span style="font-family:monospace,monospace">MSVC and </span><span style="font-family:monospace,monospace">GCC all output plain digits for Integral.</span></div></div><div><font face="monospace, monospace">Clang, </font><span style="font-family:monospace,monospace">MSVC and </span><span style="font-family:monospace,monospace">GCC* all output enum id for enumerators.</span><span style="font-family:monospace,monospace"><br></span></div><div><font face="monospace, monospace">Clang, </font><span style="font-family:monospace,monospace">MSVC </span><span style="font-family:monospace,monospace">output plain digits for </span><span style="font-family:monospace,monospace">non-enumerated values,</span><span style="font-family:monospace,monospace"><br></span></div><div><font face="monospace, monospace">while GCC outputs a C-style cast for non-enumerated values.</font></div></div><div><br></div><div><span style="font-family:monospace,monospace">*GCC enum: I submitted a bug report with a patch and tests:</span><br></div><div><div dir="ltr"><div><font face="monospace, monospace">    <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87364" target="_blank">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87364</a></font><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">(comments, subscribers or reviews will be much appreciated).</font></div><div><font face="monospace, monospace">With this fix GCC now prints </font><span style="font-family:monospace,monospace">enum id for enumerators and</span></div><div><font face="monospace, monospace">continues to print non-enumerated values by C-style cast.</font></div><div><div><font face="monospace, monospace">I plan to further investigate the Integral output for GCC.</font></div><br class="gmail-Apple-interchange-newline"></div><div><div><span style="font-family:monospace,monospace">I submitted an MSVC request for Integral and enum types:</span></div><div><font face="monospace, monospace"><a href="https://developercommunity.visualstudio.com/content/problem/339663/improve-pretty-print-of-integral-non-type-template.html">https://developercommunity.visualstudio.com/content/problem/339663/improve-pretty-print-of-integral-non-type-template.html</a></font></div></div><div><br></div><div><div><font face="monospace, monospace">How best to print the actual integral values?<br>  MSVC currently prints as '0xhhh' where h are hex digits,<br>  GCC and Clang print as 'ddd' where d are decimal digits.</font></div><font face="monospace, monospace">Decimal is less verbose, until the millions, but can be slower.</font><div><span style="font-family:monospace,monospace">Hex simplifies round-trip as it is easy to generate and parse.</span><br style="font-family:monospace,monospace"></div><div><span style="font-family:monospace,monospace">Hex is already best for reporting addresses (pointer/lval-ref).</span></div><br class="gmail-Apple-interchange-newline"></div><div><font face="monospace, monospace">It'd be good to get some consensus for Integral/enum output.</font></div><div><div><span style="font-family:monospace,monospace">Ideally we can see a coordinated change in Clang, GCC & MSVC.</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">If the suggestion here looks acceptable then I can attempt</span></div><div><span style="font-family:monospace,monospace">to update Clang printing of Integral and non-enumerated enums.</span></div><br class="gmail-Apple-interchange-newline"></div><div><br></div><div><font face="monospace, monospace"><br></font></div></div></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Sep 11, 2018 at 7:56 PM Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Mon, 10 Sep 2018 at 09:47, will wray via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</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"><div>Thanks Richard.</div><div><br></div>Ok; ignore Question 2 - you are absolutely right (what I was thinking).<div>Printing different labels for the same type defeats the point of this request.</div><div><br></div><div>OTOH, Question 1 is a request for Clang to print different output for different types.<br></div></div></div></blockquote><div><br></div><div>I think you might be under the impression that I said that we shouldn't address this, which was very much not my intent. What I tried to say was that we *should* emit a cast in the case of a deduced template parameter type, when the type of the argument expression we'd otherwise print is different from that of the parameter. That should be sufficient to ensure that Clang prints different outputs for different types. Note that special-casing enums is the wrong way to fix that problem, as the problem is not specific to enums. Consider, for example:</div><div><div><br></div><div>template<auto> struct X {};</div><div>X<(short)0> xa;</div><div>X<(long)0> xb;</div><div><br></div><div>The types of xa and xb both pretty-print as X<0> currently.</div><div><br></div><div>There are (at least) two natural ways to fix this: by always printing a cast when the type of the argument isn't the same as that of the parameter (which is the unnecessary verbosity that I was concerned with, and is what we'd get if we generalized the proposed approach for enumerations to address the whole problem), or by doing something smarter that depends on whether the template parameter was deduced (which is what I'm suggesting is the right way to address this).</div></div><div><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"><div></div><div>The linked bug report is an example of where it is important to distinguish types.</div></div></div></blockquote><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"><div>Here's a summary of suggested output vs current output for Clang, GCC, MSVC.</div><div><a href="https://godbolt.org/z/QEae7F" target="_blank">https://godbolt.org/z/QEae7F</a><br></div><div><br></div><div><span style="font-family:monospace,monospace">Plain, unscoped enum</span>  <br></div><font face="monospace, monospace">   enum e { a, b, c=b };<br>   auto_name<a, e(1), c, e(3)><br><br></font><span style="font-family:monospace,monospace">  Suggested:</span><font face="monospace, monospace"> a, b, b, (e)3<br>      Clang: a, b, b, 3<br>        GCC: (e)0, (e)1, (e)1, (e)3<br>       MSCV: 0, 1, 1, 3<br><br></font><span style="font-family:monospace,monospace">Scoped / opaque enum:</span> <font face="monospace, monospace"><br>   enum class E { a, b, c=b };<br>   auto_name<E::a, E{1}, E::c, E{3}></font><div><font face="monospace, monospace"><br></font><div><span style="font-family:monospace,monospace">  Suggested:</span><font face="monospace, monospace"> </font>

<span style="font-family:monospace,monospace">E::a, E::b, E::b, (E)3</span>  <font face="monospace, monospace"><br>      Clang: </font>

<span style="font-family:monospace,monospace">E::a, E::b, E::b</span><span style="font-family:monospace,monospace">, 3</span>  <font face="monospace, monospace"><br>        GCC: </font>

<span style="font-family:monospace,monospace">(E)0, (E)1, (E)1, (E)3</span>  <font face="monospace, monospace"><br>       MSCV: 0, 1, 1, 3</font></div><div><div><div><div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)">None of these are ideal -</div><div>- Clang loses type info for non-enumerated values.<br>- GCC does not distinguish enumerated / non-enumerated.<br>- MSVC lo<span style="color:rgb(0,0,0);background-color:rgb(255,255,254)">ses type all info, does not distinguish.</span></div></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br></div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)">Interestingly, it turns out that GCC's behaviour is a bug!</div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)">(The *intent* of gcc code is to print the suggested output.</div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"> I intend to submit a bug report and a patch.)</div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><br></div></div></div><div>You are concerned that this suggested change would</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">make the template argument string more verbose without (necessarily) providing any more information.</blockquote><div> </div><div>Yet the information is necessary in order to distinguish different types.</div><div>This change is needed for correctness.</div></div></div></div></div></blockquote><div><br></div><div>For what it's worth, I don't see a correctness concern here. Anything assuming our pretty-printed type names are unique is wrong. The bug you referenced is a bug caused by a tool getting this wrong and using the pretty type name string inappropriately, and the contributors on that bug report seem happy to acknowledge that.</div><div><br></div><div>That said, as a quality of implementation matter, we should try to ensure our pretty-printed type names are unique anyway wherever possible.</div><div><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"><div><div><div>Verbosity is a secondary concern.</div><div>Clang's current behaviour here could be treated as a bug</div><div>(it has been described as "seriously suboptimal" by a gcc dev).</div><div> </div><div>For Clang, the increased verbosity is only for non-enumerated values.</div><div>Enum-templates would be expected to mostly use enumerated values.</div><div>Also, verbosity becomes more similar for enumerated / non-enumerated</div><div>the number of characters in the identifier label vs the number of digits.</div><div><br></div><div>I'm now preferring C-style cast notation over C++ function-style</div><div>as it simplifies output and parsing code.</div><div><br></div><div>Please reflect on this and consider - is this suggested change acceptable?</div></div></div></div></div></blockquote><div><br></div><div>As noted above, the problem you described, while valid, does not justify the solution you're suggesting. However, for enums specifically, I think there's another argument to consider (one that I think you've not made yet): passing a plain integer as a template argument to an enumeration template parameter won't compile, so our pretty-printed type is not valid C++. It's reasonable to consider how valuable it is to fix that, compared with the value of having a shorter pretty-printed type name, but as you point out, we're already paying the cost of including the enum type name in the template argument in the case where an scoped enumeration is named, and an integer cast to enum type would be of comparable length. So I think the change you suggested is a good idea for that reason.</div><div><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 class="gmail_quote"><div dir="ltr">On Tue, Sep 4, 2018 at 4:30 PM Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</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 class="gmail_quote"><div dir="ltr">On Tue, 4 Sep 2018 at 09:09, will wray via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</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><a style="font-size:10pt">A request to change Clang's __PRETTY_FUNCTION__ output to fix an issue.</a></div><div><a style="font-size:10pt"><br></a></div><a style="font-size:10pt"></a><div><a style="font-size:10pt"></a><a style="font-size:10pt"></a><a style="font-size:small"></a><div style="font-size:small"><a>The code used in pretty function is also used to generate debug info in </a><a><div style="display:inline">DWARF etc</div></a><a><div style="display:inline">.</div></a></div><div style="font-size:small"><a><div style="display:inline">(I believe). See, for instance the comment on this bug report:</div></a></div><div style="font-size:small"><a><div style="display:inline">https://sourceware.org/bugzilla/show_bug.cgi?id=21492#c1</div></a></div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote"><span style="color:rgb(0,0,0);white-space:pre-wrap">Clang shows these arguments with the same DW_AT_name, X<1>, but they're distinct types</span></blockquote></div><div style="font-size:small"><span style="color:rgb(0,0,0);font-size:medium;white-space:pre-wrap"><br></span></div><div style="font-size:small"><span style="font-size:13.3333px"><a href="https://godbolt.org/z/0Ik0Hl" target="_blank">https://godbolt.org/z/0Ik0Hl</a></span><span style="color:rgb(0,0,0);font-size:medium;white-space:pre-wrap"><br></span></div>Pretty function output, for auto... args<div>(variadic just so that outputs display together):<div><span style="font-size:13.3333px"><br></span><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a style="font-size:10pt"><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div><div><div><span style="color:rgb(0,0,255)">template</span> <<span style="color:rgb(0,0,255)">auto</span>... V></div><div><span style="color:rgb(0,0,255)">constexpr</span> <span style="color:rgb(0,0,255)">char</span> <span style="color:rgb(0,0,255)">const</span>* auto_name()</div><div>{</div><div>       <span style="color:rgb(0,0,255)">return</span> __PRETTY_FUNCTION__;</div><div>}</div><br><div><span style="color:rgb(0,0,255)">enum</span> e { a, b, c=b };</div><div><span style="color:rgb(0,0,255)">enum</span> <span style="color:rgb(0,0,255)">class</span> E { a, b, c=b };</div><br><div><span style="color:rgb(0,0,255)">char</span> <span style="color:rgb(0,0,255)">const</span>* nameU() { <span style="color:rgb(0,0,255)">return</span> auto_name<a, b, c, e(<span style="color:rgb(9,136,90)">3</span>)>(); }</div><div><span style="color:rgb(0,0,255)">char</span> <span style="color:rgb(0,0,255)">const</span>* nameS() { <span style="color:rgb(0,0,255)">return</span> auto_name<E::a, E::b, E::c, E{<span style="color:rgb(9,136,90)">3</span>}>(); }</div></div></div></div></a></div></blockquote></div><div><a></a><div><a></a><div style="font-size:small"><a></a><a style="font-size:10pt"><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div><br></div></div></a></div><div style="font-size:small"><a style="font-size:10pt">Gives output with these strings embedded;</a></div></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a></a><div><a></a><div style="font-size:small"><a></a><a style="font-size:10pt">nameU: </a><a style="font-size:10pt"><div style="color:rgb(0,0,0);background-color:rgb(255,255,254);display:inline"><div style="display:inline"><span style="color:rgb(163,21,21)"><a, b, b, 3></span></div></div></a></div></div></div></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a></a><div><a>nameS: </a><a><div style="display:inline"><div style="color:rgb(0,0,0);background-color:rgb(255,255,254);display:inline"><div style="display:inline"><span style="color:rgb(163,21,21)"><E::a, E::b, E::b, 3></span></div></div></div></a></div></div></blockquote></blockquote></blockquote></blockquote></blockquote></blockquote><div><a><div><div style="font-size:small"><br></div><div style="font-size:small">The first two enumerated values, a & b, are returned with no loss of type info as a, b.</div></div><div style="font-size:small">The next enumerated value, c, is a duplicate label for b's value, and is reported as b.</div><div style="font-size:small">The final value is not enumerated - there is no enum label with value 3 -</div></a><div style="font-size:small"><a>it is reported with </a><a>an unnecessary loss of type info </a><a><div style="display:inline">as plain digits 3.</div></a></div><div style="font-size:small"><br></div><div style="font-size:small">The non-enumerated value should be reported with a cast or constructor:</div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a><div style="font-size:small">unscoped e: 3 -> (e)3 or e(3)</div></a></div></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><a><div style="display:inline">  scoped   E: 3 -> (E)3 or E(3) or E{3}</div></a></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div style="font-size:small"><a> (init-list E{3} only for scoped enum and only since c++17)</a><a><div style="display:inline">    </div></a></div></blockquote></blockquote></blockquote><div><a></a><div style="font-size:small"><a></a><a><div style="display:inline">Question 1:</div></a><br></div><div style="font-size:small">Will it be acceptable to change the output for non-enumerated values as so?</div></div></div></div></blockquote><div><br></div><div>In the case where the template parameter involves a deduced type (`auto` or `decltype(auto)` or eventually a deduced template specialization type), it would make a lot of sense to include the actual type in the printed template argument if it differs from the type of the formatted argument string. But I think we should leave out the type in all other cases, as it would make the template argument string more verbose without (necessarily) providing any more information.</div><div><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><div><div style="font-size:small"><a><div style="display:inline">This will retain type info and allow round-trip without loss.</div></a></div><div style="font-size:small">Either C-style cast (e)3  or  function-cast / type-constructor e(3) - seem ok</div><div style="font-size:small">(gcc uses C-style casts and Clang uses this same style in source labels).</div><div style="font-size:small"><br></div><div style="font-size:small">For the duplicate-valued labels case there is no loss of type info,</div><div style="font-size:small">but there is a loss of information about the label used for the auto arg.</div><div style="font-size:small">Presumably, the code works from the supplied underlying-type value</div><div style="font-size:small">and picks the first label with the given value. I'd guess that Clang knows</div><div style="font-size:small">the label used in a direct instantiation and could return it in that case.</div><div style="font-size:small">(c.f. named member-pointer args have to retain the id for reporting).</div></div></div></div></blockquote><div><br></div><div>In the case of duplicated enumerators, there simply is no distinction between 'b' and 'c' -- they are both merely names for the value 1 of type 'e'. auto_name<b>() and auto_name<c>() are the same function and therefore must return the same string.</div><div> </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><div><div style="font-size:small"><a><div style="display:inline">Question 2:</div></a><br></div><div style="font-size:small"><a><div style="display:inline">Is it possible / acceptable to retain the label in the duplicate enum value case?</div></a></div></div></div></div></blockquote><div><br></div><div>No, per the above, we cannot and must not do that.</div><div><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><div><div style="font-size:small"><a><div style="display:inline">Can anyone point me to the relevant code?</div></a></div></div></div></div></blockquote><div><br></div><div>This is printIntegral, at the top of lib/AST/TemplateBase.cpp. The "else" case at the bottom would need to print out additional text representing the cast when needed.</div></div></div>
</blockquote></div>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div></div>
</blockquote></div>