diff --git a/llvm/include/llvm/ADT/Twine.h b/llvm/include/llvm/ADT/Twine.h --- a/llvm/include/llvm/ADT/Twine.h +++ b/llvm/include/llvm/ADT/Twine.h @@ -102,14 +102,14 @@ /// A pointer to a StringRef instance. StringRefKind, -#if __cplusplus > 201402L - // A pointer to a std::string_view instance. - StdStringViewKind, -#endif - /// A pointer to a SmallString instance. SmallStringKind, + /// A Pointer and Length representation. Used for std::string_view. + /// Can't use a StringRef here because they are not trivally + /// constructible. + PtrAndLengthKind, + /// A pointer to a formatv_object_base instance. FormatvObjectKind, @@ -145,11 +145,12 @@ { const Twine *twine; const char *cString; + struct { + const char *ptr; + size_t length; + } ptrAndLength; const std::string *stdString; const StringRef *stringRef; -#if __cplusplus > 201402L - const std::string_view *stdStringView; -#endif const SmallVectorImpl *smallString; const formatv_object_base *formatvObject; char character; @@ -295,10 +296,14 @@ } #if __cplusplus > 201402L - /// Construct from an std::string_view. + /// Construct from an std::string_view by converting it to a pointer and + /// length. This handles string_views on a pure API basis, and avoids + /// storing one (or a pointer to one) inside a Twine, which avoids problems + /// when mixing code compiled under various C++ standards. /*implicit*/ Twine(const std::string_view &Str) - : LHSKind(StdStringViewKind) { - LHS.stdStringView = &Str; + : LHSKind(PtrAndLengthKind) { + LHS.ptrAndLength.ptr = Str.data(); + LHS.ptrAndLength.length = Str.length(); assert(isValid() && "Invalid twine!"); } #endif @@ -430,11 +435,9 @@ case EmptyKind: case CStringKind: case StdStringKind: -#if __cplusplus > 201402L - case StdStringViewKind: -#endif case StringRefKind: case SmallStringKind: + case PtrAndLengthKind: return true; default: return false; @@ -469,14 +472,12 @@ return StringRef(LHS.cString); case StdStringKind: return StringRef(*LHS.stdString); -#if __cplusplus > 201402L - case StdStringViewKind: - return StringRef(*LHS.stdStringView); -#endif case StringRefKind: return *LHS.stringRef; case SmallStringKind: return StringRef(LHS.smallString->data(), LHS.smallString->size()); + case PtrAndLengthKind: + return StringRef(LHS.ptrAndLength.ptr, LHS.ptrAndLength.length); } } diff --git a/llvm/lib/Support/Twine.cpp b/llvm/lib/Support/Twine.cpp --- a/llvm/lib/Support/Twine.cpp +++ b/llvm/lib/Support/Twine.cpp @@ -65,14 +65,12 @@ case Twine::CStringKind: OS << Ptr.cString; break; + case Twine::PtrAndLengthKind: + OS << StringRef(Ptr.ptrAndLength.ptr, Ptr.ptrAndLength.length); + break; case Twine::StdStringKind: OS << *Ptr.stdString; break; -#if __cplusplus > 201402L - case StdStringViewKind: - OS << StringRef(*Ptr.stdStringView); - break; -#endif case Twine::StringRefKind: OS << *Ptr.stringRef; break; @@ -124,15 +122,14 @@ OS << "cstring:\"" << Ptr.cString << "\""; break; + case Twine::PtrAndLengthKind: + OS << "ptrAndLength:\"" + << StringRef(Ptr.ptrAndLength.ptr, Ptr.ptrAndLength.length) << "\""; + break; case Twine::StdStringKind: OS << "std::string:\"" << Ptr.stdString << "\""; break; -#if __cplusplus > 201402L - case Twine::StdStringViewKind: - OS << "std::string_view:\"" << StringRef(*Ptr.stdStringView) << "\""; - break; -#endif case Twine::StringRefKind: OS << "stringref:\"" << Ptr.stringRef << "\""; diff --git a/llvm/unittests/ADT/TwineTest.cpp b/llvm/unittests/ADT/TwineTest.cpp --- a/llvm/unittests/ADT/TwineTest.cpp +++ b/llvm/unittests/ADT/TwineTest.cpp @@ -77,7 +77,7 @@ EXPECT_EQ("(Twine smallstring:\"hey\" cstring:\"there\")", repr(Twine(SmallString<7>("hey")).concat(Twine("there")))); #if __cplusplus > 201402L - EXPECT_EQ("(Twine std::string_view:\"hey\" cstring:\"there\")", + EXPECT_EQ("(Twine ptrAndLength:\"hey\" cstring:\"there\")", repr(Twine(std::string_view("hey")).concat(Twine("there")))); #endif