Index: include/llvm/ADT/Twine.h =================================================================== --- include/llvm/ADT/Twine.h +++ include/llvm/ADT/Twine.h @@ -10,6 +10,7 @@ #ifndef LLVM_ADT_TWINE_H #define LLVM_ADT_TWINE_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -100,6 +101,9 @@ /// A pointer to a StringRef instance. StringRefKind, + /// A pointer to a SmallString instance. + SmallStringKind, + /// A char value reinterpreted as a pointer, to render as a character. CharKind, @@ -136,6 +140,7 @@ const char *cString; const std::string *stdString; const StringRef *stringRef; + const SmallVectorImpl *smallString; char character; unsigned int decUI; int decI; @@ -289,6 +294,13 @@ assert(isValid() && "Invalid twine!"); } + /// Construct from a SmallString. + /*implicit*/ Twine(const SmallVectorImpl &Str) + : LHSKind(SmallStringKind), RHSKind(EmptyKind) { + LHS.smallString = &Str; + assert(isValid() && "Invalid twine!"); + } + /// Construct from a char. explicit Twine(char Val) : LHSKind(CharKind), RHSKind(EmptyKind) { @@ -402,6 +414,7 @@ case CStringKind: case StdStringKind: case StringRefKind: + case SmallStringKind: return true; default: return false; @@ -435,6 +448,8 @@ case CStringKind: return StringRef(LHS.cString); case StdStringKind: return StringRef(*LHS.stdString); case StringRefKind: return *LHS.stringRef; + case SmallStringKind: + return StringRef(LHS.smallString->data(), LHS.smallString->size()); } } Index: include/llvm/MC/MCContext.h =================================================================== --- include/llvm/MC/MCContext.h +++ include/llvm/MC/MCContext.h @@ -231,6 +231,7 @@ /// /// @param Name - The symbol name, which must be unique across all symbols. MCSymbol *GetOrCreateSymbol(StringRef Name); + MCSymbol *GetOrCreateSymbol(const SmallVectorImpl &Name); MCSymbol *GetOrCreateSymbol(const Twine &Name); MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); Index: include/llvm/Option/ArgList.h =================================================================== --- include/llvm/Option/ArgList.h +++ include/llvm/Option/ArgList.h @@ -283,7 +283,10 @@ const char *MakeArgString(const char *Str) const { return MakeArgString(StringRef(Str)); } - const char *MakeArgString(std::string Str) const { + const char *MakeArgString(const SmallVectorImpl &Str) const { + return MakeArgString(StringRef(Str.data(), Str.size())); + } + const char *MakeArgString(const std::string &Str) const { return MakeArgString(StringRef(Str)); } const char *MakeArgString(const Twine &Str) const; Index: lib/MC/MCContext.cpp =================================================================== --- lib/MC/MCContext.cpp +++ lib/MC/MCContext.cpp @@ -168,6 +168,10 @@ return CreateSymbol(NameSV); } +MCSymbol *MCContext::GetOrCreateSymbol(const SmallVectorImpl &Name) { + return GetOrCreateSymbol(StringRef(Name.data(), Name.size())); +} + MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { SmallString<128> NameSV; return GetOrCreateSymbol(Name.toStringRef(NameSV)); Index: lib/Support/Twine.cpp =================================================================== --- lib/Support/Twine.cpp +++ lib/Support/Twine.cpp @@ -72,6 +72,9 @@ case Twine::StringRefKind: OS << *Ptr.stringRef; break; + case Twine::SmallStringKind: + OS << *Ptr.smallString; + break; case Twine::CharKind: OS << Ptr.character; break; @@ -122,6 +125,10 @@ OS << "stringref:\"" << Ptr.stringRef << "\""; break; + case Twine::SmallStringKind: + OS << "smallstring:\"" + << *Ptr.smallString << "\""; + break; case Twine::CharKind: OS << "char:\"" << Ptr.character << "\""; break; Index: tools/clang/include/clang/Sema/CodeCompleteConsumer.h =================================================================== --- tools/clang/include/clang/Sema/CodeCompleteConsumer.h +++ tools/clang/include/clang/Sema/CodeCompleteConsumer.h @@ -502,13 +502,18 @@ const char *CopyString(StringRef String); /// \brief Copy the given string into this allocator. - const char *CopyString(Twine String); + const char *CopyString(const Twine &String); // \brief Copy the given string into this allocator. const char *CopyString(const char *String) { return CopyString(StringRef(String)); } + // \brief Copy the given string into this allocator. + const char *CopyString(const SmallVectorImpl &String) { + return CopyString(StringRef(String.data(), String.size())); + } + /// \brief Copy the given string into this allocator. const char *CopyString(const std::string &String) { return CopyString(StringRef(String)); Index: tools/clang/lib/Sema/CodeCompleteConsumer.cpp =================================================================== --- tools/clang/lib/Sema/CodeCompleteConsumer.cpp +++ tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -258,7 +258,7 @@ return Mem; } -const char *CodeCompletionAllocator::CopyString(Twine String) { +const char *CodeCompletionAllocator::CopyString(const Twine &String) { // FIXME: It would be more efficient to teach Twine to tell us its size and // then add a routine there to fill in an allocated char* with the contents // of the string. Index: unittests/ADT/TwineTest.cpp =================================================================== --- unittests/ADT/TwineTest.cpp +++ unittests/ADT/TwineTest.cpp @@ -29,6 +29,7 @@ EXPECT_EQ("hi", Twine(StringRef("hi")).str()); EXPECT_EQ("hi", Twine(StringRef(std::string("hi"))).str()); EXPECT_EQ("hi", Twine(StringRef("hithere", 2)).str()); + EXPECT_EQ("hi", Twine(SmallString<4>("hi")).str()); } TEST(TwineTest, Numbers) { @@ -62,6 +63,10 @@ repr(Twine("hi").concat(Twine()))); EXPECT_EQ("(Twine cstring:\"hi\" empty)", repr(Twine().concat(Twine("hi")))); + EXPECT_EQ("(Twine smallstring:\"hi\" empty)", + repr(Twine().concat(Twine(SmallString<5>("hi"))))); + EXPECT_EQ("(Twine smallstring:\"hey\" cstring:\"there\")", + repr(Twine(SmallString<7>("hey")).concat(Twine("there")))); // Concatenation of unary ropes. EXPECT_EQ("(Twine cstring:\"a\" cstring:\"b\")", @@ -72,6 +77,8 @@ repr(Twine("a").concat(Twine("b")).concat(Twine("c")))); EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine cstring:\"b\" cstring:\"c\"))", repr(Twine("a").concat(Twine("b").concat(Twine("c"))))); + EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine smallstring:\"b\" cstring:\"c\"))", + repr(Twine("a").concat(Twine(SmallString<3>("b")).concat(Twine("c"))))); } TEST(TwineTest, toNullTerminatedStringRef) { @@ -79,6 +86,9 @@ EXPECT_EQ(0, *Twine("hello").toNullTerminatedStringRef(storage).end()); EXPECT_EQ(0, *Twine(StringRef("hello")).toNullTerminatedStringRef(storage).end()); + EXPECT_EQ(0, *Twine(SmallString<11>("hello")) + .toNullTerminatedStringRef(storage) + .end()); } // I suppose linking in the entire code generator to add a unit test to check