Default values for fixed-size arrays
AidlConstantValue::ValueString() works with nested array values for
fixed-size arrays.
Bug: 207087196
Test: aidl_unittests
Change-Id: I420c23c791edd7578ebe76b5809be08c6b194e30
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index 6c4b177..14afa12 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -279,6 +279,11 @@
bool AidlBinaryConstExpression::AreCompatibleTypes(Type t1, Type t2) {
switch (t1) {
+ case Type::ARRAY:
+ if (t2 == Type::ARRAY) {
+ return true;
+ }
+ break;
case Type::STRING:
if (t2 == Type::STRING) {
return true;
@@ -329,6 +334,12 @@
AidlConstantValue* AidlConstantValue::Default(const AidlTypeSpecifier& specifier) {
AidlLocation location = specifier.GetLocation();
+ // Initialize non-nullable fixed-size arrays with {}("empty list").
+ // Each backend will handle it differently. For example, in Rust, it can be mapped to
+ // "Default::default()".
+ if (specifier.IsFixedSizeArray() && !specifier.IsNullable()) {
+ return Array(location, std::make_unique<std::vector<std::unique_ptr<AidlConstantValue>>>());
+ }
// allocation of int[0] is a bit wasteful in Java
if (specifier.IsArray()) {
return nullptr;
@@ -582,6 +593,16 @@
err = -1;
break;
}
+ if (type.IsFixedSizeArray()) {
+ auto size =
+ std::get<FixedSizeArray>(type.GetArray()).dimensions.front()->EvaluatedValue<int32_t>();
+ if (values_.size() > static_cast<size_t>(size)) {
+ AIDL_ERROR(this) << "Expected an array of " << size << " elements, but found one with "
+ << values_.size() << " elements";
+ err = -1;
+ break;
+ }
+ }
return decorator(type, value_strings);
}
case Type::FLOATING: {
diff --git a/aidl_language.cpp b/aidl_language.cpp
index d09c7c9..426fad8 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -551,10 +551,18 @@
// Declaring array of generic type cannot happen, it is grammar error.
AIDL_FATAL_IF(IsGeneric(), this);
- ArrayType array_type = std::move(array_.value());
- array_ = std::nullopt;
- func(*this);
- array_ = std::move(array_type);
+ if (IsFixedSizeArray() && std::get<FixedSizeArray>(*array_).dimensions.size() > 1) {
+ auto& dimensions = std::get<FixedSizeArray>(*array_).dimensions;
+ auto dim = std::move(dimensions.front());
+ dimensions.erase(dimensions.begin());
+ func(*this);
+ dimensions.insert(dimensions.begin(), std::move(dim));
+ } else {
+ ArrayType array_type = std::move(array_.value());
+ array_ = std::nullopt;
+ func(*this);
+ array_ = std::move(array_type);
+ }
}
bool AidlTypeSpecifier::MakeArray(ArrayType array_type) {
diff --git a/aidl_language.h b/aidl_language.h
index 266f473..1eb2737 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -401,7 +401,8 @@
vector<unique_ptr<AidlTypeSpecifier>>* type_params, const Comments& comments);
virtual ~AidlTypeSpecifier() = default;
- // View of this type which is not an array.
+ // View of this type which has one-less dimension(s).
+ // e.g.) T[] => T, T[N][M] => T[M]
void ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const;
// Returns the full-qualified name of the base type.
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index cb8fcf2..b36efcd 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -4475,6 +4475,46 @@
testing::HasSubstr("Annotations for type arguments are not supported."));
}
+TEST_F(AidlTest, DefaultShouldMatchWithFixedSizeArray) {
+ io_delegate_.SetFileContents("a/Bar.aidl",
+ "package a;\n"
+ "parcelable Bar {\n"
+ " int[2][3] a = {{1,2,3}, {4,5,6}};\n"
+ "}");
+
+ Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+ CaptureStderr();
+ EXPECT_TRUE(compile_aidl(options, io_delegate_));
+ EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithWrongTypeDefaultValue) {
+ io_delegate_.SetFileContents("a/Bar.aidl",
+ "package a;\n"
+ "parcelable Bar {\n"
+ " int[2][3] a = {{\"1\",\"2\",\"3\"}, {4,5,6}};\n"
+ "}");
+
+ Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+ CaptureStderr();
+ EXPECT_FALSE(compile_aidl(options, io_delegate_));
+ EXPECT_THAT(GetCapturedStderr(), HasSubstr("Invalid type specifier for a literal string: int"));
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithWrongSizeDefaultValue) {
+ io_delegate_.SetFileContents("a/Bar.aidl",
+ "package a;\n"
+ "parcelable Bar {\n"
+ " int[2][3] a = {{1,2,3,4}, {4,5,6}};\n"
+ "}");
+
+ Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+ CaptureStderr();
+ EXPECT_FALSE(compile_aidl(options, io_delegate_));
+ EXPECT_THAT(GetCapturedStderr(),
+ HasSubstr("Expected an array of 3 elements, but found one with 4 elements"));
+}
+
struct GenericAidlTest : ::testing::Test {
FakeIoDelegate io_delegate_;
void Compile(string cmd) {