[llvm-dev] RFC: General purpose type-safe formatting library

Zachary Turner via llvm-dev llvm-dev at lists.llvm.org
Mon Oct 31 15:45:43 PDT 2016


Hi all,

Tentatively final version is up here: https://reviews.llvm.org/D25587

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.

Here's a summary of (most) everything contained in this patch:

1) UDL Syntax for outputting to a stream or converting to a string.
    outs() << "{0}"_fmt.stream(1)
    std::string S = "{0}"_fmt.string(1);

2) Built-in format providers for various common types:
     outs() << "{0}"_fmt.stream("test");             // "test"
     outs() << "{0}"_fmt.stream(StringRef("test"));  // "test"
     outs() << "{0}"_fmt.stream(true);               // "true"
     outs() << "{0}"_fmt.stream((void*)nullptr);     // "0x00000000"

3) Customizable formatting of ranges with optionally customizable separator
    std::vector<int> X = {1, 2, 3, 4}
    outs() << "{0}"_fmt.stream(make_range(X.begin(), X.end()));
"1, 2, 3, 4"
    outs() << "{0:@[  -  ]}"_fmt.stream(make_range(X.begin(), X.end()));
 "1  -  2  -  3  -  4";

4) Left, center, and right-alignment:
    outs() << "{0:-3}"_fmt.stream(0);    "3  "
    outs() << "{0:=3}"_fmt.stream(0);    " 3 "
    outs() << "{0:3}"_fmt.stream(0);     "  3"

5) Type-specific style options:
    outs() << "{0,N}"_fmt.stream(123456);      "123,456"
    outs() << "{0,P}"_fmt.stream(0.25);        "25.00%"
    outs() << "{0,X}"_fmt.stream(0xDEADBEEF);  "0xDEADBEEF"
    outs() << "{0,X-}"_fmt.stream(0xDEADBEEF); "DEADBEEF"
    outs() << "{0,x-}"_fmt.stream(0xDEADBEEF); "deadbeef"
And many others

6) Adapters for specifying alignment, padding, and repetition with runtime
values so you don't have to dynamically manipulate a format string.
    outs() << "{0}"_fmt.stream(fmt_pad(7, 3, 5));    "   7     ";
    outs() << "{0}{1}{2}"_fmt.stream(fmt_repeat("/\\", 3), 7,
fmt_repeat("\\/", 3));   "/\/\/\7\/\/\/"

7) Compilation failures if the type cannot be formatted.
     struct Foo {};
    outs() << "{0}"_fmt.stream(Foo{});   // compilation failure.

8) Extensible format provider mechanism to allow formatting of your own
types.
    struct AddressRange { uint64_t Begin; uint64_t End; }
    template<> class format_provider<AddressRange> {
    public:
        static void format(const AddressRange &R, raw_ostream &S, StringRef
Style) {
            S << "[{0:X} - {1:X}]"_fmt.stream(R.begin(), R.end());
        }
    };
    AddressRange AR{0, 0xDEADBEEF};
    outs() << "{0}"_fmt.stream(AR);    // "[0x0 - 0xDEADBEEF]"

I'm planning to submit this towards the end of the week unless someone has
further suggestions or complaints.

On Fri, Oct 14, 2016 at 12:35 AM Nicolai Hähnle <nhaehnle at gmail.com> wrote:

> On 12.10.2016 05:59, Mehdi Amini via llvm-dev wrote:
> >>   If you change a const char * to a StringRef, it can silently succeed
> >> while passing your StringRef object to printf.  It should fail to
> compile!
> >
> > llvm::format now fails to compile as well :)
> >
> > However this does not address other issues, like: `format(“%d”,
> float_var)`
>
> This may be a good time to point at https://reviews.llvm.org/D25018
>
> But if someone ends up doing a full overhaul of the formatting that
> makes that patch unnecessary, I'm happy too.
>
> Cheers,
> Nicolai
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20161031/493f8d6c/attachment.html>


More information about the llvm-dev mailing list