Merge pull request #6 from AaronWebster/295268857
Fix bug in parameterized view copy constructor.
diff --git a/compiler/back_end/cpp/generated_code_templates b/compiler/back_end/cpp/generated_code_templates
index 09d8756..dcc82b6 100644
--- a/compiler/back_end/cpp/generated_code_templates
+++ b/compiler/back_end/cpp/generated_code_templates
@@ -80,7 +80,8 @@
template <typename OtherStorage>
Generic$_name_$View(
const Generic$_name_$View<OtherStorage> &emboss_reserved_local_other)
- : backing_{emboss_reserved_local_other.BackingStorage()} {}
+ : backing_{emboss_reserved_local_other.BackingStorage()}
+ $_parameter_copy_initializers_$ {}
// Allow pass-through construction of backing_, but only if there is at least
// one argument, and, if exactly one argument, that argument is not a
diff --git a/compiler/back_end/cpp/header_generator.py b/compiler/back_end/cpp/header_generator.py
index d3289c2..109686c 100644
--- a/compiler/back_end/cpp/header_generator.py
+++ b/compiler/back_end/cpp/header_generator.py
@@ -225,6 +225,7 @@
def _get_adapted_cpp_buffer_type_for_field(type_definition, size_in_bits,
buffer_type, byte_order,
parent_addressable_unit):
+ """Returns the adapted C++ type information needed to construct a view."""
if (parent_addressable_unit == ir_pb2.TypeDefinition.BYTE and
type_definition.addressable_unit == ir_pb2.TypeDefinition.BIT):
assert byte_order
@@ -1012,6 +1013,7 @@
constructor_parameters = []
forwarded_parameters = []
parameter_initializers = []
+ parameter_copy_initializers = []
units = {1: "Bits", 8: "Bytes"}[type_ir.addressable_unit]
for subtype in type_ir.subtype:
@@ -1030,9 +1032,12 @@
parameter_fields.append("{} {}_;".format(parameter_type, parameter_name))
constructor_parameters.append(
"{} {}, ".format(parameter_type, parameter_name))
- forwarded_parameters.append(
- "::std::forward</**/{}>({}),".format(parameter_type, parameter_name))
+ forwarded_parameters.append("::std::forward</**/{}>({}),".format(
+ parameter_type, parameter_name))
parameter_initializers.append(", {0}_({0})".format(parameter_name))
+ parameter_copy_initializers.append(
+ ", {0}_(emboss_reserved_local_other.{0}_)".format(parameter_name))
+
field_method_declarations.append(
code_template.format_template(
_TEMPLATES.structure_single_parameter_field_method_declarations,
@@ -1047,6 +1052,8 @@
field=parameter_name + "()"))
if type_ir.runtime_parameter:
flag_name = "parameters_initialized_"
+ parameter_copy_initializers.append(
+ ", {0}(emboss_reserved_local_other.{0})".format(flag_name))
parameters_initialized_flag = "bool {} = false;".format(flag_name)
initialize_parameters_initialized_true = ", {}(true)".format(flag_name)
parameter_checks = ["if (!{}) return false;".format(flag_name)]
@@ -1123,6 +1130,7 @@
constructor_parameters="".join(constructor_parameters),
forwarded_parameters="".join(forwarded_parameters),
parameter_initializers="\n".join(parameter_initializers),
+ parameter_copy_initializers="\n".join(parameter_copy_initializers),
parameters_initialized_flag=parameters_initialized_flag,
initialize_parameters_initialized_true=(
initialize_parameters_initialized_true),
diff --git a/compiler/back_end/cpp/testcode/parameters_test.cc b/compiler/back_end/cpp/testcode/parameters_test.cc
index 68b5f09..fd7d53c 100644
--- a/compiler/back_end/cpp/testcode/parameters_test.cc
+++ b/compiler/back_end/cpp/testcode/parameters_test.cc
@@ -22,9 +22,33 @@
#include "gtest/gtest.h"
#include "testdata/parameters.emb.h"
-namespace emboss_test {
+namespace emboss {
+namespace test {
namespace {
+TEST(AxisPair, Construction) {
+ ::std::array<char, 12> values = {1, 0, 0, 0, 2, 0, 0, 0};
+ auto view = MakeAxisPairView(AxisType::X_AXIS, AxisType::Y_AXIS, &values);
+
+ EXPECT_TRUE(view.Ok());
+
+ EXPECT_EQ(view.axis_type_a().Read(), AxisType::X_AXIS);
+ EXPECT_EQ(1U, view.axis_a().value().Read());
+
+ EXPECT_EQ(view.axis_type_b().Read(), AxisType::Y_AXIS);
+ EXPECT_EQ(2U, view.axis_b().value().Read());
+}
+
+TEST(AxisPair, Copy) {
+ ::std::array<char, 12> values = {1, 0, 0, 0, 2, 0, 0, 0};
+ auto view1 = MakeAxisPairView(AxisType::X_AXIS, AxisType::Y_AXIS, &values);
+ auto view2 = view1;
+
+ EXPECT_EQ(view1.Ok(), view2.Ok());
+ EXPECT_EQ(view1.axis_a().axis_type().Read(),
+ view2.axis_a().axis_type().Read());
+}
+
TEST(Axes, Construction) {
::std::array<char, 12> values = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0};
auto view = MakeAxesView(2, &values);
@@ -48,6 +72,20 @@
EXPECT_FALSE(view.Ok());
}
+TEST(Axes, Copy) {
+ ::std::array<char, 12> values = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0};
+ auto view1 = MakeAxesView(2, &values);
+ auto view2 = view1;
+
+ EXPECT_EQ(view1.Ok(), view2.Ok());
+ EXPECT_EQ(view1.values().ElementCount(), view2.values().ElementCount());
+ EXPECT_EQ(view1.values()[0].value().Read(), view2.values()[0].value().Read());
+ EXPECT_EQ(view1.x().x().Read(), view2.x().x().Read());
+ EXPECT_EQ(view1.values()[1].value().Read(), view2.values()[1].value().Read());
+ EXPECT_EQ(view1.y().y().Read(), view2.y().y().Read());
+ EXPECT_EQ(view1.has_z().Value(), view2.has_z().Value());
+}
+
TEST(Axes, VirtualUsingParameter) {
::std::array<char, 12> values = {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0};
auto view = MakeAxesView(2, &values);
@@ -70,26 +108,26 @@
EXPECT_FALSE(view.axes().Ok());
}
-TEST(Multiversion, ParameterPassedDown) {
+TEST(MultiVersion, ParameterPassedDown) {
::std::array<char, 13> values = {0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0};
- auto view = MakeMultiversionView(Product::VERSION_1, &values);
+ auto view = MakeMultiVersionView(Product::VERSION_1, &values);
EXPECT_TRUE(view.Ok());
EXPECT_EQ(2U, view.axes().y().y().Read());
EXPECT_FALSE(view.axes().has_z().Value());
- view = MakeMultiversionView(Product::VERSION_X, &values);
+ view = MakeMultiVersionView(Product::VERSION_X, &values);
EXPECT_TRUE(view.Ok());
EXPECT_EQ(2U, view.axes().y().y().Read());
EXPECT_TRUE(view.axes().has_z().Value());
}
-TEST(Multiversion, ParameterUsedToSwitchField) {
+TEST(MultiVersion, ParameterUsedToSwitchField) {
::std::array<unsigned char, 9> values = {1, 0, 0, 0, 0x80, 0, 100, 0, 0};
- auto view = MakeMultiversionView(Product::VERSION_1, &values);
+ auto view = MakeMultiVersionView(Product::VERSION_1, &values);
EXPECT_TRUE(view.Ok());
EXPECT_TRUE(view.config().power().Read());
EXPECT_FALSE(view.has_config_vx().Value());
EXPECT_EQ(5U, view.SizeInBytes());
- view = MakeMultiversionView(Product::VERSION_X, &values);
+ view = MakeMultiVersionView(Product::VERSION_X, &values);
EXPECT_TRUE(view.Ok());
EXPECT_TRUE(view.config().power().Read());
EXPECT_TRUE(view.has_config_vx().Value());
@@ -136,4 +174,5 @@
}
} // namespace
-} // namespace emboss_test
+} // namespace test
+} // namespace emboss
diff --git a/testdata/parameters.emb b/testdata/parameters.emb
index 9c28f24..2f629f3 100644
--- a/testdata/parameters.emb
+++ b/testdata/parameters.emb
@@ -20,56 +20,80 @@
VERSION_2 = 10
VERSION_X = 23
+
enum MessageId:
- AXIS = 0
+ AXIS = 0
CONFIG = 1
-struct Multiversion(product: Product):
- 0 [+1] MessageId message_id
+
+struct MultiVersion(product: Product):
+ 0 [+1] MessageId message_id
if message_id == MessageId.AXIS:
1 [+12] Axes(product == Product.VERSION_X ? 3 : 2) axes
+
if message_id == MessageId.CONFIG:
- 1 [+4] Config config
+ 1 [+4] Config config
+
if product == Product.VERSION_X && message_id == MessageId.CONFIG:
- 1 [+8] ConfigVX() config_vx
+ 1 [+8] ConfigVX() config_vx
+
struct Axes(axes: UInt:4):
- 0 [+axes * 4] Axis(AxisType.GENERIC)[] values
+ 0 [+axes*4] Axis(AxisType.GENERIC)[] values
if axes > 0:
- 0 [+4] Axis(AxisType.X_AXIS) x
+ 0 [+4] Axis(AxisType.X_AXIS) x
+
if axes > 1:
- 4 [+4] Axis(AxisType.Y_AXIS) y
+ 4 [+4] Axis(AxisType.Y_AXIS) y
+
if axes > 2:
- 8 [+4] Axis(AxisType.Z_AXIS) z
- let axis_count_plus_one = axes + 1
+ 8 [+4] Axis(AxisType.Z_AXIS) z
+
+ let axis_count_plus_one = axes+1
+
+
+struct AxisPair(axis_type_a_parameter: AxisType, axis_type_b_parameter: AxisType):
+ 0 [+4] Axis(axis_type_a) axis_a
+ 4 [+4] Axis(axis_type_b) axis_b
+ let axis_type_a = axis_type_a_parameter
+ let axis_type_b = axis_type_b_parameter
+
struct AxesEnvelope:
0 [+1] UInt:8 axis_count
1 [+axis_count*4] Axes(axis_count) axes
+
enum AxisType:
GENERIC = -1
- X_AXIS = 1
- Y_AXIS = 2
- Z_AXIS = 3
+ X_AXIS = 1
+ Y_AXIS = 2
+ Z_AXIS = 3
+
struct Axis(axis_type_parameter: AxisType):
- let axis_type = axis_type_parameter
- 0 [+4] UInt:32 value
+ 0 [+4] UInt:32 value
if axis_type == AxisType.X_AXIS:
0 [+4] UInt:32 x
+
if axis_type == AxisType.Y_AXIS:
0 [+4] UInt:32 y
+
if axis_type == AxisType.Z_AXIS:
0 [+4] UInt:32 z
+ let axis_type = axis_type_parameter
+
+
bits Config():
31 [+1] Flag power
+
struct ConfigVX:
- 0 [+4] bits:
- 31 [+1] Flag power
- 4 [+4] UInt gain
+ 0 [+4] bits:
+ 31 [+1] Flag power
+
+ 4 [+4] UInt gain
struct StructWithUnusedParameter(x: UInt:8):
@@ -78,13 +102,15 @@
# StructContainingStructWithUnusedParameter is used to ensure that a struct is
# not Ok() if it does not have its parameters, even if it does not directly use
# those parameters.
+
+
struct StructContainingStructWithUnusedParameter:
0 [+1] StructWithUnusedParameter(x) swup
1 [+1] UInt x
struct BiasedValue(bias: UInt:8):
0 [+1] UInt raw_value
- let value = raw_value + bias
+ let value = raw_value+bias
struct VirtualFirstFieldWithParam(param: UInt:8):
# Regression test: virtual fields did not have `public:` annotations, causing