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*/ 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; @@ -410,6 +430,9 @@ case EmptyKind: case CStringKind: case StdStringKind: +#if __cplusplus > 201402L + case StdStringViewKind: +#endif case StringRefKind: case SmallStringKind: return true; @@ -440,10 +463,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/include/llvm/Support/raw_ostream.h b/llvm/include/llvm/Support/raw_ostream.h --- a/llvm/include/llvm/Support/raw_ostream.h +++ b/llvm/include/llvm/Support/raw_ostream.h @@ -22,6 +22,9 @@ #include #include #include +#if __cplusplus > 201402L +#include +#endif #include #include @@ -233,6 +236,12 @@ return write(Str.data(), Str.length()); } +#if __cplusplus > 201402L + raw_ostream &operator<<(const std::string_view &Str) { + return write(Str.data(), Str.length()); + } +#endif + raw_ostream &operator<<(const SmallVectorImpl &Str) { return write(Str.data(), Str.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 @@ -68,6 +68,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 +128,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\")",