safe_union: disallow zero/single member unions.
These can't be passed between processes and aren't useful (the bare
type should be used instead).
It's needed to disallow zero member unions in order to have a default
value for hidl_o.
Bug: 116156870
Test: hidl_error_test, hidl_test, hidl_java_test
Change-Id: I4cbdfa848e774d3a5efe6f63636bdbda9eec78f2
diff --git a/CompoundType.cpp b/CompoundType.cpp
index 3ee5b10..9c3a0a9 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -70,6 +70,12 @@
}
}
+ if (mStyle == STYLE_SAFE_UNION && mFields->size() < 2) {
+ std::cerr << "ERROR: Safe union must contain at least two types to be useful at "
+ << location() << "\n";
+ return UNKNOWN_ERROR;
+ }
+
status_t err = validateUniqueNames();
if (err != OK) return err;
@@ -213,7 +219,6 @@
ErrorMode mode) const {
CHECK(mStyle == STYLE_SAFE_UNION);
- if (mFields->empty()) { return; }
out.block([&] {
const auto discriminatorType = getUnionDiscriminatorType();
@@ -564,15 +569,6 @@
? CompoundLayout()
: getCompoundAlignmentAndSize();
- if (mFields->empty()) {
- out.unindent();
- out << "};\n\n";
-
- emitLayoutAsserts(out, layout.overall, "");
- out << "\n";
- return;
- }
-
out << "enum class hidl_discriminator : "
<< getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false)
<< " ";
@@ -818,7 +814,7 @@
<< "std::string os;\n";
out << "os += \"{\";\n";
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "\nswitch (o.getDiscriminator()) {\n";
out.indent();
}
@@ -850,7 +846,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: ";
out.block([&] {
out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
@@ -867,7 +863,7 @@
<< getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
<< getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
out.block([&] {
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
out << "return false;\n";
}).endl();
@@ -898,7 +894,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: ";
out.block([&] {
out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
@@ -1184,7 +1180,6 @@
}
void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const {
- if (mFields->empty()) { return; }
emitSafeUnionTypeConstructors(out);
out << "void "
@@ -1306,7 +1301,7 @@
Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
const std::string discriminatorStorageType = (
getUnionDiscriminatorType()->getJavaType(false));
@@ -1421,7 +1416,7 @@
<< discriminatorStorageType
<< " getDiscriminator() { return hidl_d; }\n\n";
- } else if (!mFields->empty()) {
+ } else {
for (const auto& field : *mFields) {
field->emitDocComment(out);
@@ -1449,14 +1444,14 @@
}).endl();
out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out.sIf("this.hidl_d != other.hidl_d", [&] {
out << "return false;\n";
}).endl();
out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] {
out << "return false;\n";
}).endl();
- } else if (!mFields->empty()) {
+ } else {
for (const auto &field : *mFields) {
std::string condition = (field->type().isScalar() || field->type().isEnum())
? "this." + field->name() + " != other." + field->name()
@@ -1474,7 +1469,7 @@
out.block([&] {
out << "return java.util.Objects.hash(\n";
out.indent(2, [&] {
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n"
<< "java.util.Objects.hashCode(this.hidl_d)";
} else {
@@ -1496,7 +1491,7 @@
out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
<< "builder.append(\"{\");\n";
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "switch (this.hidl_d) {\n";
out.indent();
}
@@ -1527,7 +1522,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
out.unindent();
@@ -1545,7 +1540,7 @@
out.indent();
if (containsInterface()) {
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "hidl_d = ";
getUnionDiscriminatorType()->emitJavaReaderWriter(
out, "parcel", "hidl_d", true);
@@ -1572,7 +1567,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
out.unindent();
@@ -1626,7 +1621,7 @@
out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
out.unindent();
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
"_hidl_offset + " + std::to_string(layout.discriminator.offset),
@@ -1664,7 +1659,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
out.unindent();
@@ -1680,7 +1675,7 @@
out.indent();
if (containsInterface()) {
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
getUnionDiscriminatorType()->emitJavaReaderWriter(
out, "parcel", "hidl_d", false);
@@ -1703,7 +1698,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
out.unindent();
@@ -1755,7 +1750,7 @@
out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
out.unindent();
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
"_hidl_offset + " + std::to_string(layout.discriminator.offset),
@@ -1791,7 +1786,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
out.unindent();
@@ -1836,7 +1831,7 @@
out << "::android::status_t _hidl_err = ::android::OK;\n\n";
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "switch (" << name << ".getDiscriminator()) {\n";
out.indent();
}
@@ -1881,7 +1876,7 @@
}
}
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
out << "default: { break; }\n";
out.unindent();
out << "}\n";
@@ -2137,7 +2132,7 @@
Layout& innerStruct = compoundLayout.innerStruct;
Layout& discriminator = compoundLayout.discriminator;
- if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
+ if (mStyle == STYLE_SAFE_UNION) {
getUnionDiscriminatorType()->getAlignmentAndSize(
&(discriminator.align), &(discriminator.size));