diff --git a/llvm/include/llvm/ADT/Optional.h b/llvm/include/llvm/ADT/Optional.h --- a/llvm/include/llvm/ADT/Optional.h +++ b/llvm/include/llvm/ADT/Optional.h @@ -267,6 +267,14 @@ return hasValue() ? getValue() : std::forward(value); } + /// Returns the value contained in this as a ``U`` if present, otherwise + /// return \p Default. + template U getAsOr(U Default) const LLVM_LVALUE_FUNCTION { + if (hasValue()) + return static_cast(getValue()); + return Default; + } + /// Apply a function to the value if present; otherwise return None. template auto map(const Function &F) const LLVM_LVALUE_FUNCTION @@ -284,6 +292,10 @@ return hasValue() ? std::move(getValue()) : std::forward(value); } + // Delete this as it can lead to dangling reference issues if ``U`` references + // the value held in the Optional. + template U getAsOr(U Default) && = delete; + /// Apply a function to the value if present; otherwise return None. template auto map(const Function &F) && diff --git a/llvm/unittests/ADT/OptionalTest.cpp b/llvm/unittests/ADT/OptionalTest.cpp --- a/llvm/unittests/ADT/OptionalTest.cpp +++ b/llvm/unittests/ADT/OptionalTest.cpp @@ -7,13 +7,14 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Optional.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest-spi.h" #include "gtest/gtest.h" #include - +#include using namespace llvm; @@ -193,6 +194,32 @@ EXPECT_EQ(5, A.getValueOr(42)); } +TEST_F(OptionalTest, GetAsOr) { + Optional String; + StringRef Default{"DefaultOverflowSmallStringOpt"}; + StringRef Value{"Value"}; + EXPECT_EQ(Default, String.getAsOr(Default)); + String.emplace(Value); + EXPECT_EQ(Value, String.getAsOr(Default)); + + int Item = 0; + ArrayRef OneItem = makeArrayRef(Item); + ArrayRef Empty; + + Optional> SmallVec; + EXPECT_EQ(SmallVec.getAsOr(Empty).size(), 0U); + EXPECT_EQ(SmallVec.getAsOr(ArrayRef{}).size(), 0U); + EXPECT_EQ(SmallVec.getAsOr(OneItem).size(), 1U); + SmallVec.emplace(std::initializer_list{0, 1, 2, 3}); + EXPECT_EQ(SmallVec.getAsOr(Empty).size(), 4U); + + Optional> Vector; + EXPECT_EQ(Vector.getAsOr(Empty).size(), 0U); + EXPECT_EQ(Vector.getAsOr(OneItem).size(), 1U); + Vector.emplace(std::initializer_list{0, 1, 2, 3}); + EXPECT_EQ(Vector.getAsOr(Empty).size(), 4U); +} + struct MultiArgConstructor { int x, y; MultiArgConstructor(int x, int y) : x(x), y(y) {}