[llvm] r202225 - Use StringRef in raw_fd_ostream constructor

Ben Langmuir blangmuir at apple.com
Wed Feb 26 17:51:19 PST 2014


On Feb 26, 2014, at 4:57 PM, Alp Toker <alp at nuanti.com> wrote:

> 
> On 26/02/2014 17:16, Ben Langmuir wrote:
>> On Feb 26, 2014, at 7:16 AM, Ben Langmuir <blangmuir at apple.com> wrote:
>> 
>>> On Feb 25, 2014, at 9:49 PM, Alp Toker <alp at nuanti.com> wrote:
>>> 
>>>> On 26/02/2014 03:21, Ben Langmuir wrote:
>>>>> Author: benlangmuir
>>>>> Date: Tue Feb 25 21:21:00 2014
>>>>> New Revision: 202225
>>>>> 
>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=202225&view=rev
>>>>> Log:
>>>>> Use StringRef in raw_fd_ostream constructor
>>>>> 
>>>>> Modified:
>>>>>    llvm/trunk/include/llvm/Support/raw_ostream.h
>>>>>    llvm/trunk/lib/Support/raw_ostream.cpp
>>>>> 
>>>>> Modified: llvm/trunk/include/llvm/Support/raw_ostream.h
>>>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=202225&r1=202224&r2=202225&view=diff
>>>>> ==============================================================================
>>>>> --- llvm/trunk/include/llvm/Support/raw_ostream.h (original)
>>>>> +++ llvm/trunk/include/llvm/Support/raw_ostream.h Tue Feb 25 21:21:00 2014
>>>>> @@ -346,7 +346,7 @@ public:
>>>>>   /// itself to own the file descriptor. In particular, it will close the
>>>>>   /// file descriptor when it is done (this is necessary to detect
>>>>>   /// output errors).
>>>>> -  raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
>>>>> +  raw_fd_ostream(StringRef Filename, std::string &ErrorInfo,
>>>>>                  sys::fs::OpenFlags Flags);
>>>> Filenames are a special case in LLVM that get passed around as an opaque const char* often without ever needing having their length measured (like the clang driver code I'm looking at right now).
>>>> 
>>>> Your change will incur a strlen() upon every ctor call: not a great problem, but also somewhat redundant -- was there a need that triggered this change?
>>> I intend to make FileEntry in Clang own the storage for its file name,
> 
> Anecdotally, I believe FileEntry used to have storage with an std::string back in the days before SVN history. There's also an old proposal in NOTES.txt to change it to a sys::Path (which doesn't exist any more). These days it's a POD structure that gets passed around a lot so I'd think twice about such a change if it's avoidable.

Only references to FileEntry are passed around.  There is exactly one place in Clang that copies a FileEntry (and as a point of interest, it is safe to use a move constructor instead).  I think having FileEntry own the storage is going to be fine.

> 
> 
>>>  which seemed like a good opportunity to change the FileEntry getName to return a StringRef, particularly because it is currently being used/abused to also check if the FileEntry is initialized.  This was one of the pieces that uses that name, so I thought I’d avoid a string copy before passing it in.
>>> 
>>> What if I switch to raw_fd_ostream(const Twine &Filename, …)?  Then if it is null-terminated we don’t need the strlen call.
>> Actually, given what you just told me, is changing FIleEntry to use StringRef even a good idea? I could potentially just use c_str() to get the pointer now that I have identified all the places that were checking for a null result.
> 
> Although there's no strict convention, const char* has benefits over StringRef for file paths:
> 
> * Discourages non-portable path manipulation/comparison. Wherever we've passed around paths as StringRefs sooner or later someone goes ahead and tries if (a == b) ... which passes tests but fails in real environments.

As David Blaikie points out, I see several uses of strcmp, some of which look totally safe, others I’m not sure about.  I’ll also point out that the sys::path APIs generally use StringRef.

> 
> * Ensures the presence of a null terminator. Low-level filesystem ops require a null-terminated C string so if we pass around StringRefs there's a risk we'll have to incur a copy just to null-terminate the string. Not requiring strlen() is a corollary to that.

Okay, I buy this.  There are some places that construct StringRefs from filenames, so we are paying this cost elsewhere, but I have no data to say that I would be improving the situation.

> 
> So If you can get away with c_str(), it's best to keep the const char* status quo IMO. If that isn't possible, a Twine is a second best (indeed the underlying LLVM abstractions work with a Twine).

 I’ll revert this patch and use c_str.

> If however it turns out you actually do need storage for FileEntry, we should review the changes together in context because that has wider impact.

I do need storage, but I’ll keep that hidden in the FileEntry for now.

Thanks,

Ben

> 
> Alp.
> 
> 
> 
>> 
>> Ben
>> 
>>> Ben
>>> 
>>>> Alp.
>>>> 
>>>>>     /// raw_fd_ostream ctor - FD is the file descriptor that this writes to.  If
>>>>> 
>>>>> Modified: llvm/trunk/lib/Support/raw_ostream.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=202225&r1=202224&r2=202225&view=diff
>>>>> ==============================================================================
>>>>> --- llvm/trunk/lib/Support/raw_ostream.cpp (original)
>>>>> +++ llvm/trunk/lib/Support/raw_ostream.cpp Tue Feb 25 21:21:00 2014
>>>>> @@ -430,16 +430,15 @@ void format_object_base::home() {
>>>>> /// occurs, information about the error is put into ErrorInfo, and the
>>>>> /// stream should be immediately destroyed; the string will be empty
>>>>> /// if no error occurred.
>>>>> -raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
>>>>> +raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::string &ErrorInfo,
>>>>>                                sys::fs::OpenFlags Flags)
>>>>>     : Error(false), UseAtomicWrites(false), pos(0) {
>>>>> -  assert(Filename != 0 && "Filename is null");
>>>>>   ErrorInfo.clear();
>>>>>     // Handle "-" as stdout. Note that when we do this, we consider ourself
>>>>>   // the owner of stdout. This means that we can do things like close the
>>>>>   // file descriptor when we're done and set the "binary" flag globally.
>>>>> -  if (Filename[0] == '-' && Filename[1] == 0) {
>>>>> +  if (Filename == "-") {
>>>>>     FD = STDOUT_FILENO;
>>>>>     // If user requested binary then put stdout into binary mode if
>>>>>     // possible.
>>>>> 
>>>>> 
>>>>> _______________________________________________
>>>>> llvm-commits mailing list
>>>>> llvm-commits at cs.uiuc.edu
>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>> -- 
>>>> http://www.nuanti.com
>>>> the browser experts
> 
> -- 
> http://www.nuanti.com
> the browser experts





More information about the llvm-commits mailing list