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; @@ -294,13 +295,20 @@ assert(isValid() && "Invalid twine!"); } -#if __cplusplus > 201402L - /// Construct from an std::string_view. - /*implicit*/ Twine(const std::string_view &Str) - : LHSKind(StdStringViewKind) { - LHS.stdStringView = &Str; + /*implicit*/ Twine(const char *ptr, size_t length) + : LHSKind(PtrAndLengthKind) { + LHS.ptrAndLength.ptr = ptr; + LHS.ptrAndLength.length = length; assert(isValid() && "Invalid twine!"); } + +#if __cplusplus > 201402L + /// Construct from an std::string_view by converting it to a StringRef. + /// 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) + : Twine(Str.data(), Str.length()) {} #endif /// Construct from a StringRef. @@ -430,11 +438,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 +475,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,9 @@ 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\")", + // string_views are immediately converted to stringrefs to avoid + // C++ standard dependencies. + EXPECT_EQ("(Twine ptrAndLength:\"hey\" cstring:\"there\")", repr(Twine(std::string_view("hey")).concat(Twine("there")))); #endif