<div dir="ltr"><div>Hi all,</div><div><br></div><div>Tentatively final version is up here: <a href="https://reviews.llvm.org/D25587">https://reviews.llvm.org/D25587</a></div><div><br></div><div>It has a verbal LGTM, but I plan to wait a bit longer just in case anyone has some additional thoughts.  It's a large patch, but if you're interested, one way you can help without doing a full-blown review is to look at the large comment blocks in FormatVariadic.h and FormatProviders.h.  Here I provide a formal description of the grammar of the replacement sequences and format syntax.  So you can look at this without looking at the code behind it and see if you have comments just on the format language.</div><div><br></div><div>Here's a summary of (most) everything contained in this patch:</div><div><br></div><div>1) UDL Syntax for outputting to a stream or converting to a string.</div><div><font face="monospace">    outs() << "{0}"_fmt.stream(1)</font></div><div><font face="monospace">    std::string S = "{0}"_fmt.string(1);</font></div><div><br></div><div>2) Built-in format providers for various common types:</div><div><font face="monospace">     outs() << "{0}"_fmt.stream("test");             // "test"</font></div><div><font face="monospace">     outs() << "{0}"_fmt.stream(StringRef("test"));  // "test"</font></div><div><font face="monospace">     outs() << "{0}"_fmt.stream(true);               // "true"<br></font></div><div><font face="monospace">     outs() << "{0}"_fmt.stream((void*)nullptr);     // "0x00000000"</font></div><div><font face="monospace"><br></font></div><div>3) Customizable formatting of ranges with optionally customizable separator</div><div><font face="monospace">    std::vector<int> X = {1, 2, 3, 4}</font></div><div><font face="monospace">    outs() << "{0}"_fmt.stream(make_range(X.begin(), X.end()));             "1, 2, 3, 4"</font></div><div><font face="monospace">    outs() << "{0:@[  -  ]}"_fmt.stream(make_range(X.begin(), X.end()));    "1  -  2  -  3  -  4";</font></div><div><br></div><div>4) Left, center, and right-alignment:</div><div><font face="monospace">    outs() << "{0:-3}"_fmt.stream(0);    "3  "</font></div><div><font face="monospace">    outs() << "{0:=3}"_fmt.stream(0);    " 3 "</font></div><div><font face="monospace">    outs() << "{0:3}"_fmt.stream(0);     "  3"</font><br></div><div><br></div><div>5) Type-specific style options:</div><div><font face="monospace">    outs() << "{0,N}"_fmt.stream(123456);      "123,456"</font></div><div><font face="monospace">    outs() << "{0,P}"_fmt.stream(0.25);        "25.00%"</font></div><div><font face="monospace">    outs() << "{0,X}"_fmt.stream(0xDEADBEEF);  "0xDEADBEEF"</font></div><div><font face="monospace">    outs() << "{0,X-}"_fmt.stream(0xDEADBEEF); "DEADBEEF"  <br></font></div><div><font face="monospace">    outs() << "{0,x-}"_fmt.stream(0xDEADBEEF); "deadbeef"  </font><br></div><div>And many others</div><div><br></div><div>6) Adapters for specifying alignment, padding, and repetition with runtime values so you don't have to dynamically manipulate a format string.</div><div><font face="monospace">    outs() << "{0}"_fmt.stream(fmt_pad(7, 3, 5));    "   7     ";</font></div><div><font face="monospace">    outs() << "{0}{1}{2}"_fmt.stream(fmt_repeat("/\\", 3), 7, fmt_repeat("\\/", 3));   "/\/\/\7\/\/\/"</font></div><div><br></div><div>7) Compilation failures if the type cannot be formatted.<br></div><div>     <font face="monospace">struct Foo {};</font></div><div><div><font face="monospace">    outs() << "{0}"_fmt.stream(Foo{});   // compilation failure.</font></div><div><br></div></div><div>8) Extensible format provider mechanism to allow formatting of your own types.<br></div><div><font face="monospace">    struct AddressRange { uint64_t Begin; uint64_t End; }</font></div><div><font face="monospace">    template<> class format_provider<AddressRange> {</font></div><div><font face="monospace">    public:</font></div><div><font face="monospace">        static void format(const AddressRange &R, raw_ostream &S, StringRef Style) {</font></div><div><font face="monospace">            S << "[{0:X} - {1:X}]"_fmt.stream(R.begin(), R.end());</font></div><div><font face="monospace">        }</font></div><div><font face="monospace">    };</font></div><div><font face="monospace">    AddressRange AR</font><span style="font-family:monospace;font-size:10.5625px">{0, 0xDEADBEEF};</span></div><div><font face="monospace">    outs() << "{0}"_fmt.stream(AR);    // "[0x0 - 0xDEADBEEF]"</font></div><div><font face="monospace"><br></font></div><div>I'm planning to submit this towards the end of the week unless someone has further suggestions or complaints.</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Oct 14, 2016 at 12:35 AM Nicolai Hähnle <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 12.10.2016 05:59, Mehdi Amini via llvm-dev wrote:<br class="gmail_msg">
>>   If you change a const char * to a StringRef, it can silently succeed<br class="gmail_msg">
>> while passing your StringRef object to printf.  It should fail to compile!<br class="gmail_msg">
><br class="gmail_msg">
> llvm::format now fails to compile as well :)<br class="gmail_msg">
><br class="gmail_msg">
> However this does not address other issues, like: `format(“%d”, float_var)`<br class="gmail_msg">
<br class="gmail_msg">
This may be a good time to point at <a href="https://reviews.llvm.org/D25018" rel="noreferrer" class="gmail_msg" target="_blank">https://reviews.llvm.org/D25018</a><br class="gmail_msg">
<br class="gmail_msg">
But if someone ends up doing a full overhaul of the formatting that<br class="gmail_msg">
makes that patch unnecessary, I'm happy too.<br class="gmail_msg">
<br class="gmail_msg">
Cheers,<br class="gmail_msg">
Nicolai<br class="gmail_msg">
</blockquote></div>