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 @@ -15,6 +15,9 @@ #include #include #include +#if __cplusplus > 201402L +#include +#endif namespace llvm { @@ -99,6 +102,11 @@ /// 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, @@ -139,6 +147,9 @@ const char *cString; 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; @@ -283,6 +294,15 @@ assert(isValid() && "Invalid twine!"); } +#if __cplusplus > 201402L + /// Construct from an std::string_view. + /*implicit*/ constexpr Twine(const std::string_view &Str) + : LHSKind(StdStringViewKind) { + LHS.stdStringView = &Str; + assert(isValid() && "Invalid twine!"); + } +#endif + /// Construct from a StringRef. /*implicit*/ Twine(const StringRef &Str) : LHSKind(StringRefKind) { LHS.stringRef = &Str; @@ -361,6 +381,16 @@ assert(isValid() && "Invalid twine!"); } +#if __cplusplus > 201402L + /// Construct as the concatenation of a C string and a std::string_view. + /*implicit*/ Twine(const char *LHS, const std::string_view *RHS) + : LHSKind(CStringKind), RHSKind(StdStringViewKind) { + this->LHS.cString = LHS; + this->RHS.stdStringView = RHS; + assert(isValid() && "Invalid twine!"); + } +#endif + /// Construct as the concatenation of a StringRef and a C string. /*implicit*/ Twine(const StringRef &LHS, const char *RHS) : LHSKind(StringRefKind), RHSKind(CStringKind) { @@ -410,6 +440,9 @@ case EmptyKind: case CStringKind: case StdStringKind: +#if __cplusplus > 201402L + case StdStringViewKind: +#endif case StringRefKind: case SmallStringKind: return true; @@ -440,10 +473,18 @@ assert(isSingleStringRef() &&"This cannot be had as a single stringref!"); switch (getLHSKind()) { default: llvm_unreachable("Out of sync with isSingleStringRef"); - case EmptyKind: return StringRef(); - case CStringKind: return StringRef(LHS.cString); - case StdStringKind: return StringRef(*LHS.stdString); - case StringRefKind: return *LHS.stringRef; + case EmptyKind: + return StringRef(); + case CStringKind: + 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()); } 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 @@ -44,6 +44,12 @@ const std::string *str = LHS.stdString; return StringRef(str->c_str(), str->size()); } +#if __cplusplus > 201402L + case StdStringViewKind: { + const std::string_view *str = LHS.stdStringView; + return StringRef(str->data(), str->size()); + } +#endif default: break; } @@ -68,6 +74,11 @@ 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; @@ -123,6 +134,11 @@ 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 @@ -32,6 +32,9 @@ EXPECT_EQ("hi", Twine(StringRef("hithere", 2)).str()); EXPECT_EQ("hi", Twine(SmallString<4>("hi")).str()); EXPECT_EQ("hi", Twine(formatv("{0}", "hi")).str()); +#if __cplusplus > 201402L + EXPECT_EQ("hi", Twine(std::string_view("hi")).str()); +#endif } TEST(TwineTest, Numbers) { @@ -73,6 +76,10 @@ repr(Twine().concat(Twine(formatv("howdy"))))); 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\")", + repr(Twine(std::string_view("hey")).concat(Twine("there")))); +#endif // Concatenation of unary ropes. EXPECT_EQ("(Twine cstring:\"a\" cstring:\"b\")",