@@ -1390,6 +1390,188 @@ class opt_storage<DataType, false, true> : public DataType {
13901390 const OptionValue<DataType> &getDefault () const { return Default; }
13911391};
13921392
1393+ // Define a fully-specialized version of opt_storage for std::string. This
1394+ // implementation avoids inheriting from std::string while still being
1395+ // compatible with it in most common use cases.
1396+ //
1397+ template <> class opt_storage <std::string, false , true > {
1398+ using Self = opt_storage<std::string, false , true >;
1399+
1400+ public:
1401+ std::string Value;
1402+ OptionValue<std::string> Default;
1403+
1404+ // Make sure we initialize the value with the default constructor for the
1405+ // type.
1406+ opt_storage () : Value(std::string()), Default() {}
1407+
1408+ template <class T > void setValue (const T &V, bool initial = false ) {
1409+ Value = static_cast <std::string>(V);
1410+ if (initial)
1411+ Default = static_cast <std::string>(V);
1412+ }
1413+
1414+ std::string &getValue () { return Value; }
1415+ std::string getValue () const { return Value; }
1416+
1417+ const OptionValue<std::string> &getDefault () const { return Default; }
1418+
1419+ // Support implicit conversions to std::string and LLVM string-like types.
1420+ // operator std::string() const { return Value; }
1421+ operator std::string &() { return Value; }
1422+ operator const std::string &() const { return Value; }
1423+ operator llvm::StringRef () const { return llvm::StringRef (Value); }
1424+ operator llvm::Twine () const { return llvm::Twine (llvm::StringRef (Value)); }
1425+
1426+ // If the datatype is a pointer, support -> on it.
1427+ std::string operator ->() const { return Value; }
1428+
1429+ Self &operator =(const Self &rhs) = default ;
1430+
1431+ Self &operator =(const std::string &rhs) {
1432+ Value = rhs;
1433+ return *this ;
1434+ }
1435+
1436+ Self &operator =(const char *rhs) {
1437+ Value = rhs;
1438+ return *this ;
1439+ }
1440+
1441+ // Implement a subset of std::string methods
1442+ size_t size () const noexcept { return Value.size (); };
1443+ size_t max_size () const noexcept { return Value.max_size (); };
1444+ size_t length () const noexcept { return Value.length (); };
1445+ bool empty () const noexcept { return Value.empty (); }
1446+ void clear () noexcept { Value.clear (); }
1447+
1448+ const char *c_str () const { return Value.c_str (); };
1449+ const char *data () const { return Value.data (); };
1450+
1451+ auto begin () noexcept { return Value.begin (); }
1452+ auto end () noexcept { return Value.end (); }
1453+ auto begin () const noexcept { return Value.begin (); }
1454+ auto end () const noexcept { return Value.end (); }
1455+ auto cbegin () const noexcept { return Value.cbegin (); }
1456+ auto cend () const noexcept { return Value.cend (); }
1457+
1458+ auto rbegin () noexcept { return Value.rbegin (); }
1459+ auto rend () noexcept { return Value.rend (); }
1460+ auto rbegin () const noexcept { return Value.rbegin (); }
1461+ auto rend () const noexcept { return Value.rend (); }
1462+ auto crbegin () const noexcept { return Value.rbegin (); }
1463+ auto crend () const noexcept { return Value.rend (); }
1464+
1465+ void erase (size_t pos = 0 , size_t count = std::string::npos) {
1466+ Value.erase (pos, count);
1467+ }
1468+
1469+ size_t find (const std::string &str, size_t pos = 0 ) const {
1470+ return Value.find (str, pos);
1471+ }
1472+
1473+ size_t find (const char *s, size_t pos = 0 ) const {
1474+ return Value.find (s, pos);
1475+ }
1476+
1477+ size_t find (char c, size_t pos = 0 ) const { return Value.find (c, pos); }
1478+
1479+ std::string substr (size_t pos = 0 , size_t count = std::string::npos) const {
1480+ return Value.substr (pos, count);
1481+ }
1482+
1483+ char &at (size_t pos) { return Value[pos]; }
1484+ const char &at (size_t pos) const { return Value.at (pos); }
1485+
1486+ char &front () { return Value.front (); }
1487+ const char &front () const { return Value.front (); }
1488+
1489+ char &back () { return Value.back (); }
1490+ const char &back () const { return Value.back (); }
1491+
1492+ char operator [](size_t pos) const { return Value.at (pos); }
1493+
1494+ Self &assign (const std::string &rhs) {
1495+ Value.assign (rhs);
1496+ return *this ;
1497+ }
1498+
1499+ Self &assign (const char *rhs) {
1500+ Value.assign (rhs);
1501+ return *this ;
1502+ }
1503+
1504+ Self &operator +=(const std::string &rhs) {
1505+ Value += rhs;
1506+ return *this ;
1507+ }
1508+
1509+ Self &operator +=(const char *rhs) {
1510+ Value += rhs;
1511+ return *this ;
1512+ }
1513+
1514+ friend std::string operator +(Self const &lhs, std::string const &rhs) {
1515+ return lhs.Value + rhs;
1516+ }
1517+
1518+ friend std::string operator +(std::string const &lhs, Self const &rhs) {
1519+ return lhs + rhs.Value ;
1520+ }
1521+
1522+ friend std::string operator +(Self const &lhs, char const *rhs) {
1523+ return lhs.Value + rhs;
1524+ }
1525+
1526+ friend std::string operator +(char const *lhs, Self const &rhs) {
1527+ return lhs + rhs.Value ;
1528+ }
1529+
1530+ friend bool operator ==(const Self &lhs, const Self &rhs) {
1531+ return lhs.Value == rhs.Value ;
1532+ }
1533+
1534+ friend bool operator ==(const Self &lhs, const std::string &rhs) {
1535+ return lhs.Value == rhs;
1536+ }
1537+
1538+ friend bool operator ==(const Self &lhs, const char *rhs) {
1539+ return lhs.Value == rhs;
1540+ }
1541+
1542+ friend bool operator ==(const std::string &lhs, const Self &rhs) {
1543+ return lhs == rhs.Value ;
1544+ }
1545+
1546+ friend bool operator ==(const char *lhs, const Self &rhs) {
1547+ return lhs == rhs.Value ;
1548+ }
1549+
1550+ friend bool operator !=(const Self &lhs, const Self &rhs) {
1551+ return lhs.Value != rhs.Value ;
1552+ }
1553+
1554+ friend bool operator !=(const Self &lhs, const std::string &rhs) {
1555+ return lhs.Value != rhs;
1556+ }
1557+
1558+ friend bool operator !=(const Self &lhs, const char *rhs) {
1559+ return lhs.Value != rhs;
1560+ }
1561+
1562+ friend bool operator !=(const std::string &lhs, const Self &rhs) {
1563+ return lhs != rhs.Value ;
1564+ }
1565+
1566+ friend bool operator !=(const char *lhs, const Self &rhs) {
1567+ return lhs != rhs.Value ;
1568+ }
1569+
1570+ friend raw_ostream &operator <<(raw_ostream &os, const Self &str) {
1571+ return os << str.Value ;
1572+ }
1573+ };
1574+
13931575// Define a partial specialization to handle things we cannot inherit from. In
13941576// this case, we store an instance through containment, and overload operators
13951577// to get at the value.
0 commit comments