xref: /aosp_15_r20/external/pigweed/pw_toolchain/sibling_cast_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_toolchain/internal/sibling_cast.h"
16 
17 #include "pw_compilation_testing/negative_compilation.h"
18 #include "pw_unit_test/framework.h"
19 
20 namespace pw::internal {
21 namespace {
22 
23 class Base {
24  public:
Base(char id)25   constexpr Base(char id) : lowercase_id_{id} {}
26 
27  protected:
28   char lowercase_id_;
29 };
30 
31 class DerivedA : public Base {
32  public:
DerivedA()33   constexpr DerivedA() : Base('a') {}
34 
35   // Lowercase version of the ID.
Id() const36   char Id() const { return lowercase_id_; }
37 };
38 
39 class DerivedB : public Base {
40  public:
DerivedB()41   constexpr DerivedB() : Base('b') {}
42 
43   // Capitalized version of the ID.
Id() const44   char Id() const { return lowercase_id_ - ('a' - 'A'); }
45 };
46 
47 constexpr DerivedA kInstanceA;
48 constexpr DerivedB kInstanceB;
49 
TEST(SiblingCast,Reference)50 TEST(SiblingCast, Reference) {
51   DerivedA instance_a;
52   DerivedB instance_b;
53 
54   EXPECT_EQ(instance_a.Id(), 'a');
55   DerivedB& b_ref = SiblingCast<DerivedB&, Base>(instance_a);
56   EXPECT_EQ(b_ref.Id(), 'A');
57 
58   EXPECT_EQ(instance_b.Id(), 'B');
59   DerivedA& a_ref = SiblingCast<DerivedA&, Base>(instance_b);
60   EXPECT_EQ(a_ref.Id(), 'b');
61 }
62 
TEST(SiblingCast,RvalueReference)63 TEST(SiblingCast, RvalueReference) {
64   DerivedA instance_a;
65   DerivedB instance_b;
66 
67   EXPECT_EQ(instance_a.Id(), 'a');
68   DerivedB&& b_ref = SiblingCast<DerivedB&&, Base>(std::move(instance_a));
69   EXPECT_EQ(b_ref.Id(), 'A');
70 
71   EXPECT_EQ(instance_b.Id(), 'B');
72   DerivedA&& a_ref = SiblingCast<DerivedA&&, Base>(std::move(instance_b));
73   EXPECT_EQ(a_ref.Id(), 'b');
74 }
75 
TEST(SiblingCast,ConstReference)76 TEST(SiblingCast, ConstReference) {
77   EXPECT_EQ(kInstanceA.Id(), 'a');
78   const DerivedB& b_ref = SiblingCast<const DerivedB&, Base>(kInstanceA);
79   EXPECT_EQ(b_ref.Id(), 'A');
80 
81   EXPECT_EQ(kInstanceB.Id(), 'B');
82   const DerivedA& a_ref = SiblingCast<const DerivedA&, Base>(kInstanceB);
83   EXPECT_EQ(a_ref.Id(), 'b');
84 }
85 
TEST(SiblingCast,ConstRvalueReference)86 TEST(SiblingCast, ConstRvalueReference) {
87   EXPECT_EQ(kInstanceA.Id(), 'a');
88   const DerivedB&& b_ref =
89       SiblingCast<const DerivedB&&, Base>(std::move(kInstanceA));
90   EXPECT_EQ(b_ref.Id(), 'A');
91 
92   EXPECT_EQ(kInstanceB.Id(), 'B');
93   const DerivedA&& a_ref =
94       SiblingCast<const DerivedA&&, Base>(std::move(kInstanceB));
95   EXPECT_EQ(a_ref.Id(), 'b');
96 }
97 
TEST(SiblingCast,NonConstToConstReference)98 TEST(SiblingCast, NonConstToConstReference) {
99   DerivedA instance_a;
100   DerivedB instance_b;
101 
102   EXPECT_EQ(instance_a.Id(), 'a');
103   const DerivedB& b_ref = SiblingCast<const DerivedB&, Base>(instance_a);
104   EXPECT_EQ(b_ref.Id(), 'A');
105 
106   EXPECT_EQ(instance_b.Id(), 'B');
107   const DerivedA& a_ref = SiblingCast<const DerivedA&, Base>(instance_b);
108   EXPECT_EQ(a_ref.Id(), 'b');
109 }
110 
TEST(SiblingCast,Pointer)111 TEST(SiblingCast, Pointer) {
112   DerivedA instance_a;
113   DerivedB instance_b;
114 
115   EXPECT_EQ(instance_a.Id(), 'a');
116   DerivedB* b_ptr = SiblingCast<DerivedB*, Base>(&instance_a);
117   EXPECT_EQ(b_ptr->Id(), 'A');
118 
119   EXPECT_EQ(instance_b.Id(), 'B');
120   DerivedA* a_ptr = SiblingCast<DerivedA*, Base>(&instance_b);
121   EXPECT_EQ(a_ptr->Id(), 'b');
122 }
123 
TEST(SiblingCast,ConstPointer)124 TEST(SiblingCast, ConstPointer) {
125   EXPECT_EQ(kInstanceA.Id(), 'a');
126   const DerivedB* b_ptr = SiblingCast<const DerivedB*, Base>(&kInstanceA);
127   EXPECT_EQ(b_ptr->Id(), 'A');
128 
129   EXPECT_EQ(kInstanceB.Id(), 'B');
130   const DerivedA* a_ptr = SiblingCast<const DerivedA*, Base>(&kInstanceB);
131   EXPECT_EQ(a_ptr->Id(), 'b');
132 }
133 
TEST(SiblingCast,NonConstToConstPointer)134 TEST(SiblingCast, NonConstToConstPointer) {
135   DerivedA instance_a;
136   DerivedB instance_b;
137 
138   EXPECT_EQ(instance_a.Id(), 'a');
139   const DerivedB* b_ptr = SiblingCast<const DerivedB*, Base>(&instance_a);
140   EXPECT_EQ(b_ptr->Id(), 'A');
141 
142   EXPECT_EQ(instance_b.Id(), 'B');
143   const DerivedA* a_ptr = SiblingCast<const DerivedA*, Base>(&instance_b);
144   EXPECT_EQ(a_ptr->Id(), 'b');
145 }
146 
147 class DerivedExtra : public Base {
148  public:
DerivedExtra()149   DerivedExtra() : Base('e') {}
150 
member() const151   int member() const { return member_; }
152 
153  private:
154   int member_ = 0;
155 };
156 
157 class DerivedMultiple : public DerivedA, DerivedB {
158  public:
DerivedMultiple()159   DerivedMultiple() {}
160 };
161 
TEST(SiblingCast,NegativeCompilationTests)162 TEST(SiblingCast, NegativeCompilationTests) {
163   DerivedMultiple multiple;
164   DerivedExtra extra;
165 #if PW_NC_TEST(AmbiguousBase)
166   PW_NC_EXPECT("unambiguously derive from the base");
167   [[maybe_unused]] DerivedB& b_ref = SiblingCast<DerivedB&, Base>(multiple);
168 #elif PW_NC_TEST(SourceTypeCannotAddMembers)
169   PW_NC_EXPECT("source type cannot add any members");
170   [[maybe_unused]] DerivedB& b_ref = SiblingCast<DerivedB&, Base>(extra);
171 #elif PW_NC_TEST(DestinationTypeCannotAddMembers)
172   PW_NC_EXPECT("destination type cannot add any members");
173   [[maybe_unused]] auto& e = SiblingCast<const DerivedExtra&, Base>(kInstanceA);
174 #endif  // PW_NC_TEST
175 }
176 
177 }  // namespace
178 }  // namespace pw::internal
179