/// 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,
{
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<char> *smallString;
const formatv_object_base *formatvObject;
char character;
}
#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
case EmptyKind:
case CStringKind:
case StdStringKind:
-#if __cplusplus > 201402L
- case StdStringViewKind:
-#endif
case StringRefKind:
case SmallStringKind:
+ case PtrAndLengthKind:
return true;
default:
return false;
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);
}
}
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;
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 << "\"";
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