[PATCH] D25446: Disallow ArrayRef assignment from temporaries

Duncan P. N. Exon Smith via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 17 10:03:20 PDT 2016


> On 2016-Oct-17, at 09:44, David Blaikie <dblaikie at gmail.com> wrote:
> 
> 
> 
> On Mon, Oct 10, 2016 at 1:24 PM Duncan P. N. Exon Smith via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> > On 2016-Oct-10, at 12:35, Jordan Rose <jordan_rose at apple.com> wrote:
> >
> > jordan_rose created this revision.
> > jordan_rose added reviewers: chandlerc, dexonsmith.
> > jordan_rose added a subscriber: llvm-commits.
> > jordan_rose set the repository for this revision to rL LLVM.
> >
> > Without this, the following statements will create ArrayRefs that refer to temporary storage that goes out of scope by the end of the line:
> >
> >  c++
> >  someArrayRef = getSingleElement();
> >  someArrayRef = {elem1, elem2};
> >
> > Note that the constructor still has this problem:
> >
> >  c++
> >  ArrayRef<Element> someArrayRef = getSingleElement();
> >  ArrayRef<Element> someArrayRef = {elem1, elem2};
> 
> Long-term, I think these constructors should be explicit.
> 
> > but that's a little harder to get rid of because we want to be able to use this in calls:
> >
> >  c++
> >  takesArrayRef(getSingleElement());
> >  takesArrayRef({elem1, elem2});
> 
> These would have to change to:
> 
>     takesArrayRef(makeArrayRef(getSingleElement()));
>     takesArrayRef(makeArrayRef({elem1, elem2}));
> 
> but I think that would be a fine tradeoff.
> 
> I wouldn't be so sure - we rely on these implicit conversions (similarly for StringRef) a /lot/. But maybe it's less bad than I imagine.

I had a look a few years ago and abandoned; it would/will be a lot of pain to make the change.  But IMO the end result is better than the current state.

> (what I'd really like is a clang-tidy check integrated into the compilation/build pipeline somehow... - I'm still waiting for that integration, at which point we can have project specific and otherwise "low value" (things that'd usually have too high signal/noise to add to Clang let alone enable by default in Clang) warnings/errors)
>  
> 
> >
> > Part of rdar://problem/16375365.
> >
> >
> > Repository:
> >  rL LLVM
> >
> > https://reviews.llvm.org/D25446
> >
> > Files:
> >  include/llvm/ADT/ArrayRef.h
> >
> >
> > Index: include/llvm/ADT/ArrayRef.h
> > ===================================================================
> > --- include/llvm/ADT/ArrayRef.h
> > +++ include/llvm/ADT/ArrayRef.h
> > @@ -219,6 +219,22 @@
> >       return Data[Index];
> >     }
> >
> > +    /// Disallow accidental assignment from a temporary.
> > +    ///
> > +    /// The declaration here is extra complicated so that "arrayRef = {}"
> > +    /// continues to select the move assignment operator.
> > +    template <typename U>
> > +    typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
> > +    operator=(U &&Temporary) = delete;
> 
> I'm not sure the parameter name, "Temporary", is worth spelling out.
> 
> LGTM (with or without the name) if you add std::is_assignable-based static_asserts to unittests/ADT/ArrayRefTest.cpp.
> 
> > +
> > +    /// Disallow accidental assignment from a temporary.
> > +    ///
> > +    /// The declaration here is extra complicated so that "arrayRef = {}"
> > +    /// continues to select the move assignment operator.
> > +    template <typename U>
> > +    typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
> > +    operator=(std::initializer_list<U>) = delete;
> > +
> >     /// @}
> >     /// @name Expensive Operations
> >     /// @{
> >
> >
> > <D25446.74161.patch>
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list