mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:40:12 +01:00
Disables three new warnings because they lean more towards style conflicts than fixes. I've brought these up on #style. Other than that, mostly fixing basic issues, and things that clang-tidy-20 seems to fire where clang-tiday-16 didn't. One particular curious case is `llvm::StringLiteral::data()` uses, which are flagged as not strictly null-terminated; I'm switching to `const char*` in those spots which matches `llvm::formatv`'s format argument, but feels worse. I'm removing `run_clang_tidy.py` here because I'm observing it give fewer warnings than `bazel build --config=clang-tidy -k //toolchain/...`. The latter matches how we enforce in GitHub actions (and also caches results, and suppresses output for files that have no issues), so I'm dropping the bespoke script.
131 lines
3.4 KiB
C++
131 lines
3.4 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "common/indirect_value.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <string>
|
|
|
|
namespace Carbon {
|
|
namespace {
|
|
|
|
TEST(IndirectValueTest, ConstAccess) {
|
|
const IndirectValue<int> v = 42;
|
|
EXPECT_EQ(*v, 42);
|
|
EXPECT_EQ(v.GetPointer(), &*v);
|
|
}
|
|
|
|
TEST(IndirectValueTest, MutableAccess) {
|
|
IndirectValue<int> v = 42;
|
|
EXPECT_EQ(*v, 42);
|
|
EXPECT_EQ(v.GetPointer(), &*v);
|
|
*v = 0;
|
|
EXPECT_EQ(*v, 0);
|
|
}
|
|
|
|
struct NonMovable {
|
|
explicit NonMovable(int i) : i(i) {}
|
|
NonMovable(NonMovable&&) = delete;
|
|
auto operator=(NonMovable&&) -> NonMovable& = delete;
|
|
|
|
int i;
|
|
};
|
|
|
|
TEST(IndirectValueTest, Create) {
|
|
IndirectValue<NonMovable> v =
|
|
MakeIndirectValue([] { return NonMovable(42); });
|
|
EXPECT_EQ(v->i, 42);
|
|
}
|
|
|
|
auto GetIntReference() -> const int& {
|
|
static int i = 42;
|
|
return i;
|
|
}
|
|
|
|
TEST(IndirectValueTest, CreateWithDecay) {
|
|
auto v = MakeIndirectValue(GetIntReference);
|
|
EXPECT_TRUE((std::is_same_v<decltype(v), IndirectValue<int>>));
|
|
EXPECT_EQ(*v, 42);
|
|
}
|
|
|
|
// Test double which presents a value-like interface, but tracks which special
|
|
// member function (if any) caused it to reach its present value.
|
|
struct TestValue {
|
|
TestValue() : state("default constructed") {}
|
|
TestValue(const TestValue& /*rhs*/) : state("copy constructed") {}
|
|
TestValue(TestValue&& other) noexcept : state("move constructed") {
|
|
other.state = "move constructed from";
|
|
}
|
|
auto operator=(const TestValue& /*unused*/) noexcept -> TestValue& {
|
|
state = "copy assigned";
|
|
return *this;
|
|
}
|
|
auto operator=(TestValue&& other) noexcept -> TestValue& {
|
|
state = "move assigned";
|
|
other.state = "move assigned from";
|
|
return *this;
|
|
}
|
|
|
|
std::string state;
|
|
};
|
|
|
|
TEST(IndirectValueTest, ConstArrow) {
|
|
const IndirectValue<TestValue> v;
|
|
EXPECT_EQ(v->state, "default constructed");
|
|
}
|
|
|
|
TEST(IndirectValueTest, MutableArrow) {
|
|
IndirectValue<TestValue> v;
|
|
EXPECT_EQ(v->state, "default constructed");
|
|
v->state = "explicitly set";
|
|
EXPECT_EQ(v->state, "explicitly set");
|
|
}
|
|
|
|
TEST(IndirectValueTest, CopyConstruct) {
|
|
IndirectValue<TestValue> v1;
|
|
// NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
|
|
auto v2 = v1;
|
|
EXPECT_EQ(v1->state, "default constructed");
|
|
EXPECT_EQ(v2->state, "copy constructed");
|
|
}
|
|
|
|
TEST(IndirectValueTest, CopyAssign) {
|
|
IndirectValue<TestValue> v1;
|
|
IndirectValue<TestValue> v2;
|
|
v2 = v1;
|
|
EXPECT_EQ(v1->state, "default constructed");
|
|
EXPECT_EQ(v2->state, "copy assigned");
|
|
}
|
|
|
|
TEST(IndirectValueTest, MoveConstruct) {
|
|
IndirectValue<TestValue> v1;
|
|
auto v2 = std::move(v1);
|
|
// While not entirely safe, the `v1->state` access tests move behavior.
|
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
|
EXPECT_EQ(v1->state, "move constructed from");
|
|
EXPECT_EQ(v2->state, "move constructed");
|
|
}
|
|
|
|
TEST(IndirectValueTest, MoveAssign) {
|
|
IndirectValue<TestValue> v1;
|
|
IndirectValue<TestValue> v2;
|
|
v2 = std::move(v1);
|
|
// While not entirely safe, the `v1->state` access tests move behavior.
|
|
// NOLINTNEXTLINE(bugprone-use-after-move)
|
|
EXPECT_EQ(v1->state, "move assigned from");
|
|
EXPECT_EQ(v2->state, "move assigned");
|
|
}
|
|
|
|
TEST(IndirectValueTest, IncompleteType) {
|
|
struct S {
|
|
std::optional<IndirectValue<S>> v;
|
|
};
|
|
|
|
S s = {.v = S{}};
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace Carbon
|