Skip to content

Commit 1c5dea5

Browse files
committed
[llvm] specialize cl::opt_storage for std::string
1 parent ed2bfd1 commit 1c5dea5

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

llvm/include/llvm/Support/CommandLine.h

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,10 @@ class Triple {
358358
explicit Triple(const std::string &Str) : Triple(std::string(Str)) {}
359359
LLVM_ABI explicit Triple(const Twine &Str);
360360

361+
template <typename S, typename = std::enable_if_t<
362+
std::is_convertible<S, StringRef>::value>>
363+
explicit Triple(const S &Str) : Triple(StringRef(Str)) {}
364+
361365
LLVM_ABI Triple(const Twine &ArchStr, const Twine &VendorStr,
362366
const Twine &OSStr);
363367
LLVM_ABI Triple(const Twine &ArchStr, const Twine &VendorStr,

0 commit comments

Comments
 (0)