Skip to content

Commit

Permalink
PR51018: Disallow explicit construction of StringRef from SmallString…
Browse files Browse the repository at this point in the history
… due to ambiguity in C++23

See bug for full details, but basically there's an upcoming ambiguity in
the conversion in `StringRef(SomeSmallString)` - either the implicit
conversion operator (SmallString::operator StringRef) could be used, or
the std::string_view range-based ctor (& then `StringRef(std::string_view)`
would be used)

To address this, make such a conversion invalid up-front - most uses are
more tersely written as `SomeSmallString.str()` anyway, or more clearly
written as `StringRef x = y;` rather than `StringRef x(y);` - so if you
hit this in out-of-tree code, please update in one of those ways.
Hopefully I've fixed everything in tree prior to this patch landing.
  • Loading branch information
dwblaikie committed Jul 8, 2021
1 parent 1def257 commit e2d3084
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions llvm/include/llvm/ADT/SmallString.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,22 @@

namespace llvm {

namespace impl {
template <typename T> struct SmallStringConversionHelper1 {
operator StringRef() const { return static_cast<const T *>(this)->str(); }
};
struct SmallStringConversionHelper2 {
explicit operator StringRef() const = delete;
};
} // namespace impl

/// SmallString - A SmallString is just a SmallVector with methods and accessors
/// that make it work better as a string (e.g. operator+ etc).
template<unsigned InternalLen>
class SmallString : public SmallVector<char, InternalLen> {
template <unsigned InternalLen>
class SmallString
: public SmallVector<char, InternalLen>,
public impl::SmallStringConversionHelper1<SmallString<InternalLen>>,
public impl::SmallStringConversionHelper2 {
public:
/// Default ctor - Initialize to empty.
SmallString() = default;
Expand Down Expand Up @@ -266,7 +278,6 @@ class SmallString : public SmallVector<char, InternalLen> {
}

/// Implicit conversion to StringRef.
operator StringRef() const { return str(); }

explicit operator std::string() const {
return std::string(this->data(), this->size());
Expand Down

0 comments on commit e2d3084

Please sign in to comment.