Commit f24c956a authored by Daniel Cheng's avatar Daniel Cheng Committed by Commit Bot

base::Optional: CHECK if attempting to dereference no set value.

base::Optional::value() already does this; change operator* and
operator-> to match, and ensure the behavior is tested.

Change-Id: Id686b86d0e68360dea3a92d01206aefde6782a16
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1531498
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#649250}
parent 2f89e530
...@@ -568,32 +568,32 @@ class OPTIONAL_DECLSPEC_EMPTY_BASES Optional ...@@ -568,32 +568,32 @@ class OPTIONAL_DECLSPEC_EMPTY_BASES Optional
} }
constexpr const T* operator->() const { constexpr const T* operator->() const {
DCHECK(storage_.is_populated_); CHECK(storage_.is_populated_);
return &storage_.value_; return &storage_.value_;
} }
constexpr T* operator->() { constexpr T* operator->() {
DCHECK(storage_.is_populated_); CHECK(storage_.is_populated_);
return &storage_.value_; return &storage_.value_;
} }
constexpr const T& operator*() const & { constexpr const T& operator*() const & {
DCHECK(storage_.is_populated_); CHECK(storage_.is_populated_);
return storage_.value_; return storage_.value_;
} }
constexpr T& operator*() & { constexpr T& operator*() & {
DCHECK(storage_.is_populated_); CHECK(storage_.is_populated_);
return storage_.value_; return storage_.value_;
} }
constexpr const T&& operator*() const && { constexpr const T&& operator*() const && {
DCHECK(storage_.is_populated_); CHECK(storage_.is_populated_);
return std::move(storage_.value_); return std::move(storage_.value_);
} }
constexpr T&& operator*() && { constexpr T&& operator*() && {
DCHECK(storage_.is_populated_); CHECK(storage_.is_populated_);
return std::move(storage_.value_); return std::move(storage_.value_);
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -2119,6 +2120,29 @@ TEST(OptionalTest, DontCallNewMemberFunction) { ...@@ -2119,6 +2120,29 @@ TEST(OptionalTest, DontCallNewMemberFunction) {
EXPECT_TRUE(a.has_value()); EXPECT_TRUE(a.has_value());
} }
TEST(OptionalTest, DereferencingNoValueCrashes) {
class C {
public:
void Method() const {}
};
{
const Optional<C> const_optional;
EXPECT_CHECK_DEATH(const_optional.value());
EXPECT_CHECK_DEATH(const_optional->Method());
EXPECT_CHECK_DEATH(*const_optional);
EXPECT_CHECK_DEATH(*std::move(const_optional));
}
{
Optional<C> non_const_optional;
EXPECT_CHECK_DEATH(non_const_optional.value());
EXPECT_CHECK_DEATH(non_const_optional->Method());
EXPECT_CHECK_DEATH(*non_const_optional);
EXPECT_CHECK_DEATH(*std::move(non_const_optional));
}
}
TEST(OptionalTest, Noexcept) { TEST(OptionalTest, Noexcept) {
// Trivial copy ctor, non-trivial move ctor, nothrow move assign. // Trivial copy ctor, non-trivial move ctor, nothrow move assign.
struct Test1 { struct Test1 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment