[LLVMdev] Addressing const reference in ArrayRef

Duncan P. N. Exon Smith dexonsmith at apple.com
Fri Aug 22 10:16:47 PDT 2014


> On 2014-Aug-21, at 10:39, David Blaikie <dblaikie at gmail.com> wrote:
> 
> On Thu, Aug 21, 2014 at 10:34 AM, Reid Kleckner <rnk at google.com> wrote:
>> Is there some way we can get lifetime extension of temporaries to kick in
>> here?
> 
> Nope - since the temporary is a subexpression - not the thing being declared.
> 


>>>>>> We could move this ctor into a factory function (and/or just make the
>>>>>> CTor
>>>>>> private and friend the makeArrayRef helper for this case) to make it
>>>>>> more
>>>>>> obvious/easier to find bad call sites. But it would be helpful to
>>>>>> have
>>>>>> the
>>>>>> context of the prior discussion to continue from there.

A variation of these solutions makes sense to me.  I strongly dislike
this constructor since it leads to other subtle bugs.  E.g., suppose you
have this API:

    void foo(ArrayRef<const char *> Strings);

and some caller uses `foo("string")`.

If you change the API to add an optional `bool`:

    void foo(ArrayRef<const char *> Strings, bool B = false);
    void foo(bool B = false);

the caller silently switches to `foo(bool("string"))` instead of
`foo(ArrayRef<const char *>("string"))`.

If we remove the `ArrayRef` constructor AND the helper, and add a new
helper like:

    template <class T> ArrayRef<T> makeTempArrayRef(const T &OneElt) {
      return ArrayRef<T>(&OneElt, &OneElt + 1);
    }

then both types of bugs will be more rare and obvious.

For the OP's case, the name "Temp" makes it more clear that the ArrayRef
shouldn't be named.  For my case, since the caller is forced to use
`foo(makeTempArrayRef("string"))`, it's easier to make safe API changes.

This would cause a lot of churn though -- ArrayRefs are *usually*
temporaries.  Although this makes sense to me, disallowing named
ArrayRefs might be more practical.



More information about the llvm-dev mailing list