The filesystem implementation used variadic templates to convert path
arguments to C strings, but in the process, format string checks for
vsnprintf was lost. The latter is more useful than the former, so prefer
the simpler code. While here, fix a small bug in the va_list handling as
the initial list could be va_end'd twice, once by the second vsnprintf
and another time by the guard itself.
Details
- Reviewers
• Quuxplusone - Group Reviewers
Restricted Project
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Just a few comments from a quick look.
libcxx/include/__config | ||
---|---|---|
1452 | Does clang-cl support this attribute? If yes, then it should be #if defined(__GNUC_) || defined(__clang__). | |
1453 | The macro name is misleading for me. It doesn't print, and it doesn't print files. It annotates a printf-like function though. | |
libcxx/src/filesystem/directory_iterator.cpp | ||
275 | @mstorsjo, you probably need to sync on this part regarding https://reviews.llvm.org/D98077. | |
libcxx/src/filesystem/filesystem_common.h | ||
78 | Typo. |
libcxx/include/__config | ||
---|---|---|
1453 | Looks like the typical name would be _LIBCPP_FORMAT_PRINTF. (Compare _LIBCPP_NOALIAS, _LIBCPP_NORETURN, _LIBCPP_ALWAYS_INLINE, etc.) | |
libcxx/src/filesystem/filesystem_common.h | ||
210 | It looks like you're trying to make sure that va_end is called even during exception-based stack unwinding, is that right? If so, I think you should do the RAII thing and create a proper struct type that calls va_end in its destructor. Hey, it looks like GuardVaList might already be that RAII type! Use it on line 209, and on line 218, and on line 113. Don't call va_end manually on line 189 — let these GuardVaList objects deal with that cleanup. Basically, make sure every time you call va_start or va_copy, you follow it immediately with a transfer of ownership to a GuardVaList. |
libcxx/include/__config | ||
---|---|---|
1452 | It seems to work as is with clang-cl. | |
1453 | Yeah, C&P of a type. It should have been _LIBCPP_PRINTFLIKE. I'm not sure _LIBCPP_FORMAT_PRINTF is better, but I'm not really attached to the name either way. | |
libcxx/src/filesystem/filesystem_common.h | ||
210 | I don't think there is any advantage to moving GuardVaList out. If anything, calling format_string_impl first and building the result afterwards seems like the way forward as it removes the only possible exception path. |
libcxx/src/filesystem/filesystem_common.h | ||
---|---|---|
210 | ...Actually, I take back the "RAII guard" idea. From OSX's man stdarg:
And see https://stackoverflow.com/questions/37454179/how-to-properly-va-end So you should just figure out a way to make report_impl noexcept, and then do both va_start and va_end from within this function. (format_string_impl will continue to call both va_copy and va_end from within the same function; but again, it shouldn't use the RAII type to do it; it should just be made noexcept.) Also, please pass va_list ap by value, not reference; that way we match what libc does with vprintf, which we know is OK. Pass-by-reference is probably fine in practice, but why take the chance? |
libcxx/include/__config | ||
---|---|---|
1452 | I just tested it and __GNUC__ is *not* defined by clang-cl. |
libcxx/include/__config | ||
---|---|---|
1452 | I would like to proceed with D98097, and @joerg has said D98097 works for him as well. It's still waiting on libc++ approval though, so, ping! :) |
libcxx/include/__config | ||
---|---|---|
1452 | That's exactly this. |
Does clang-cl support this attribute? If yes, then it should be #if defined(__GNUC_) || defined(__clang__).