[fidl] Initial support for extensible unions.
Implements extensible unions ("xunions") described in FTP-015.
Differences with the FTP:
* We use "xunion" as a keyword to define an extensible union, rather
than "union".
* "union" continues to define a static union, which still exists, and is
unchanged.
* Ordinals are calculated using FTP-020. Explicit ordinals are not
allowed.
* Zero is an allowed ordinal, and indicates that the xunion is empty.
* No reserved field support yet, since ordinal hashing may make this
unnecessary.
Happy to discuss any of the above points, of course!
Test: make HOST_USE_ASAN=true tools && $FUCHSIA_DIR/zircon/build-x64/host_tests/fidl-compiler-test
Change-Id: Ib07d6135099424dd7a617c6f3af8579122e92418
diff --git a/system/host/fidl/examples/types.fidl b/system/host/fidl/examples/types.fidl
index fd143a7..9ed961f 100644
--- a/system/host/fidl/examples/types.fidl
+++ b/system/host/fidl/examples/types.fidl
@@ -339,3 +339,8 @@
request<this_is_an_interface> r;
request<this_is_an_interface>? nullable_r;
};
+
+xunion this_is_a_xunion {
+ string s;
+ int32 i;
+};
diff --git a/system/host/fidl/examples/xunion.fidl b/system/host/fidl/examples/xunion.fidl
new file mode 100644
index 0000000..4857c52
--- /dev/null
+++ b/system/host/fidl/examples/xunion.fidl
@@ -0,0 +1,16 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library fidl.examples.xunion;
+
+table t {
+ 1: string s;
+};
+
+xunion xu {
+ int32 i;
+ float32 f;
+ string s;
+ [Selector = "v2"] vector<int64> v;
+};
diff --git a/system/host/fidl/include/fidl/c_generator.h b/system/host/fidl/include/fidl/c_generator.h
index 45eb108..8093330 100644
--- a/system/host/fidl/include/fidl/c_generator.h
+++ b/system/host/fidl/include/fidl/c_generator.h
@@ -108,6 +108,11 @@
const flat::Union& union_info;
};
+ struct NamedXUnion {
+ std::string name;
+ const flat::XUnion& xunion_info;
+ };
+
enum class StructKind {
kMessage,
kNonmessage,
@@ -124,6 +129,7 @@
void GenerateStructDeclaration(StringView name, const std::vector<Member>& members, StructKind kind);
void GenerateTaggedUnionDeclaration(StringView name, const std::vector<Member>& members);
+ void GenerateTaggedXUnionDeclaration(StringView name, const std::vector<Member>& members);
std::map<const flat::Decl*, NamedConst>
NameConsts(const std::vector<std::unique_ptr<flat::Const>>& const_infos);
@@ -137,6 +143,8 @@
NameTables(const std::vector<std::unique_ptr<flat::Table>>& table_infos);
std::map<const flat::Decl*, NamedUnion>
NameUnions(const std::vector<std::unique_ptr<flat::Union>>& union_infos);
+ std::map<const flat::Decl*, NamedXUnion>
+ NameXUnions(const std::vector<std::unique_ptr<flat::XUnion>>& xunion_infos);
void ProduceConstForwardDeclaration(const NamedConst& named_const);
void ProduceEnumForwardDeclaration(const NamedEnum& named_enum);
@@ -144,6 +152,7 @@
void ProduceStructForwardDeclaration(const NamedStruct& named_struct);
void ProduceTableForwardDeclaration(const NamedTable& named_table);
void ProduceUnionForwardDeclaration(const NamedUnion& named_union);
+ void ProduceXUnionForwardDeclaration(const NamedXUnion& named_xunion);
void ProduceInterfaceExternDeclaration(const NamedInterface& named_interface);
@@ -153,6 +162,7 @@
void ProduceStructDeclaration(const NamedStruct& named_struct);
void ProduceTableDeclaration(const NamedStruct& named_struct);
void ProduceUnionDeclaration(const NamedUnion& named_union);
+ void ProduceXUnionDeclaration(const NamedXUnion& named_xunion);
void ProduceInterfaceClientDeclaration(const NamedInterface& named_interface);
void ProduceInterfaceClientImplementation(const NamedInterface& named_interface);
diff --git a/system/host/fidl/include/fidl/coded_ast.h b/system/host/fidl/include/fidl/coded_ast.h
index 26675ab..6701117 100644
--- a/system/host/fidl/include/fidl/coded_ast.h
+++ b/system/host/fidl/include/fidl/coded_ast.h
@@ -46,6 +46,11 @@
const uint32_t offset;
};
+// This carries the same information as the XUnionField struct below and
+// arguably violates DRY, but it's useful to make it a different type to
+// distinguish its use-case in code, and also to make it easier to change later
+// if necessary. (Gotta do something at least three times before we abstract it
+// out, right?)
struct TableField {
TableField(const Type* type, uint32_t ordinal)
: type(type), ordinal(ordinal) {}
@@ -54,6 +59,18 @@
const uint32_t ordinal;
};
+// This carries the same information as the TableField struct above and arguably
+// violates DRY, but it's useful to make it a different type to distinguish its
+// use-case in code, and also to make it easier to change later if necessary.
+// (Gotta do something at least three times before we abstract it out, right?)
+struct XUnionField {
+ XUnionField(const Type* type, uint32_t ordinal)
+ : type(type), ordinal(ordinal) {}
+
+ const Type* type;
+ const uint32_t ordinal;
+};
+
struct Type {
virtual ~Type() = default;
@@ -68,6 +85,8 @@
kTablePointer,
kUnion,
kUnionPointer,
+ kXUnion,
+ kXUnionPointer,
kMessage,
kInterface,
kArray,
@@ -181,6 +200,27 @@
const UnionType* union_type;
};
+struct XUnionType : public Type {
+ XUnionType(std::string name, std::vector<XUnionField> fields,
+ std::string pointer_name, std::string qname)
+ : Type(Kind::kXUnion, std::move(name), 24u, CodingNeeded::kNeeded), fields(std::move(fields)),
+ pointer_name(std::move(pointer_name)), qname(std::move(qname)) {
+ }
+
+ std::vector<XUnionField> fields;
+ const std::string pointer_name;
+ const std::string qname;
+ bool referenced_by_pointer = false;
+};
+
+struct XUnionPointerType : public Type {
+ XUnionPointerType(std::string name, const XUnionType* xunion_type)
+ : Type(Kind::kXUnionPointer, std::move(name), 8u, CodingNeeded::kNeeded),
+ xunion_type(xunion_type) {}
+
+ const XUnionType* const xunion_type;
+};
+
struct MessageType : public Type {
MessageType(std::string name, std::vector<StructField> fields, uint32_t size, std::string qname)
: Type(Kind::kMessage, std::move(name), size, CodingNeeded::kNeeded),
diff --git a/system/host/fidl/include/fidl/flat_ast.h b/system/host/fidl/include/fidl/flat_ast.h
index ced6f9d..d4bd4de 100644
--- a/system/host/fidl/include/fidl/flat_ast.h
+++ b/system/host/fidl/include/fidl/flat_ast.h
@@ -425,6 +425,7 @@
kStruct,
kTable,
kUnion,
+ kXUnion,
};
Decl(Kind kind, std::unique_ptr<raw::AttributeList> attributes, Name name)
@@ -765,6 +766,25 @@
bool recursive = false;
};
+struct XUnion : public Decl {
+ struct Member {
+ Member(std::unique_ptr<raw::Ordinal> ordinal, std::unique_ptr<Type> type, SourceLocation name, std::unique_ptr<raw::AttributeList> attributes)
+ : ordinal(std::move(ordinal)), type(std::move(type)), name(std::move(name)), attributes(std::move(attributes)) {}
+ std::unique_ptr<raw::Ordinal> ordinal;
+ std::unique_ptr<Type> type;
+ SourceLocation name;
+ std::unique_ptr<raw::AttributeList> attributes;
+ FieldShape fieldshape;
+ };
+
+ XUnion(std::unique_ptr<raw::AttributeList> attributes, Name name, std::vector<Member> members)
+ : Decl(Kind::kXUnion, std::move(attributes), std::move(name)), members(std::move(members)) {}
+
+ std::vector<Member> members;
+ TypeShape typeshape;
+ bool recursive = false;
+};
+
struct Interface : public Decl {
struct Method {
Method(Method&&) = default;
@@ -964,6 +984,8 @@
kTableMember,
kUnionDecl,
kUnionMember,
+ kXUnionDecl,
+ kXUnionMember,
};
AttributeSchema(const std::set<Placement>& allowed_placements,
@@ -1094,6 +1116,7 @@
bool ConsumeStructDeclaration(std::unique_ptr<raw::StructDeclaration> struct_declaration);
bool ConsumeTableDeclaration(std::unique_ptr<raw::TableDeclaration> table_declaration);
bool ConsumeUnionDeclaration(std::unique_ptr<raw::UnionDeclaration> union_declaration);
+ bool ConsumeXUnionDeclaration(std::unique_ptr<raw::XUnionDeclaration> xunion_declaration);
bool TypeCanBeConst(const Type* type);
const Type* TypeResolve(const Type* type);
@@ -1134,6 +1157,7 @@
bool CompileStruct(Struct* struct_declaration);
bool CompileTable(Table* table_declaration);
bool CompileUnion(Union* union_declaration);
+ bool CompileXUnion(XUnion* xunion_declaration);
// Compiling a type both validates the type, and computes shape
// information for the type. In particular, we validate that
@@ -1176,6 +1200,7 @@
std::vector<std::unique_ptr<Struct>> struct_declarations_;
std::vector<std::unique_ptr<Table>> table_declarations_;
std::vector<std::unique_ptr<Union>> union_declarations_;
+ std::vector<std::unique_ptr<XUnion>> xunion_declarations_;
// All Decl pointers here are non-null and are owned by the
// various foo_declarations_.
diff --git a/system/host/fidl/include/fidl/formatter.h b/system/host/fidl/include/fidl/formatter.h
index c8049e9..3a5854b 100644
--- a/system/host/fidl/include/fidl/formatter.h
+++ b/system/host/fidl/include/fidl/formatter.h
@@ -149,11 +149,24 @@
}
virtual void OnUnionMember(std::unique_ptr<UnionMember> const& element) override {
- ScopedBool mem(is_member_decl_);
OnBlankLineRespectingNode();
+ ScopedBool mem(is_member_decl_);
TreeVisitor::OnUnionMember(element);
}
+ virtual void OnXUnionDeclaration(std::unique_ptr<XUnionDeclaration> const& element) override {
+ OnBlankLineRequiringNode();
+ TreeVisitor::OnXUnionDeclaration(element);
+ }
+
+ virtual void OnXUnionMember(std::unique_ptr<XUnionMember> const& element) override {
+ OnBlankLineRespectingNode();
+ ScopedBool mem(is_member_decl_);
+ ScopedBool before_colon(blank_space_before_colon_, false);
+ ScopedBool after_colon(blank_space_after_colon_, true);
+ TreeVisitor::OnXUnionMember(element);
+ }
+
virtual void OnType(std::unique_ptr<Type> const& element) override {
ScopedIncrement si(nested_type_depth_);
ScopedBool before_colon(blank_space_before_colon_, false);
diff --git a/system/host/fidl/include/fidl/json_generator.h b/system/host/fidl/include/fidl/json_generator.h
index 6ff50f8..8f7c1ea 100644
--- a/system/host/fidl/include/fidl/json_generator.h
+++ b/system/host/fidl/include/fidl/json_generator.h
@@ -96,6 +96,8 @@
void Generate(const flat::Table::Member& value);
void Generate(const flat::Union& value);
void Generate(const flat::Union::Member& value);
+ void Generate(const flat::XUnion& value);
+ void Generate(const flat::XUnion::Member& value);
void Generate(const flat::Library* library);
void GenerateDeclarationsEntry(int count, const flat::Name& name, StringView decl);
diff --git a/system/host/fidl/include/fidl/names.h b/system/host/fidl/include/fidl/names.h
index 8f4e28a..6fc3860 100644
--- a/system/host/fidl/include/fidl/names.h
+++ b/system/host/fidl/include/fidl/names.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef ZIRCON_SYSTEM_HOST_FIDL_INCLUDE_FIDL_C_NAMES_H_
-#define ZIRCON_SYSTEM_HOST_FIDL_INCLUDE_FIDL_C_NAMES_H_
+#ifndef ZIRCON_SYSTEM_HOST_FIDL_INCLUDE_FIDL_NAMES_H_
+#define ZIRCON_SYSTEM_HOST_FIDL_INCLUDE_FIDL_NAMES_H_
#include <string>
@@ -34,6 +34,7 @@
std::string NameFlatConstantKind(flat::Constant::Kind kind);
std::string NameFlatTypeKind(flat::Type::Kind kind);
std::string NameUnionTag(StringView union_name, const flat::Union::Member& member);
+std::string NameXUnionTag(StringView xunion_name, const flat::XUnion::Member& member);
std::string NameFlatConstant(const flat::Constant* constant);
std::string NameFlatType(const flat::Type* type);
std::string NameFlatCType(const flat::Type* type, flat::Decl::Kind decl_kind);
@@ -51,6 +52,7 @@
std::string NameCodedStruct(const flat::Struct* struct_decl);
std::string NameCodedTable(const flat::Table* table_decl);
std::string NameCodedUnion(const flat::Union* union_decl);
+std::string NameCodedXUnion(const flat::XUnion* xunion_decl);
std::string NameCodedHandle(types::HandleSubtype subtype, types::Nullability nullability);
std::string NameCodedInterfaceHandle(StringView interface_name, types::Nullability nullability);
std::string NameCodedRequestHandle(StringView interface_name, types::Nullability nullability);
@@ -61,4 +63,4 @@
} // namespace fidl
-#endif // ZIRCON_SYSTEM_HOST_FIDL_INCLUDE_FIDL_C_NAMES_H_
+#endif // ZIRCON_SYSTEM_HOST_FIDL_INCLUDE_FIDL_NAMES_H_
diff --git a/system/host/fidl/include/fidl/ordinals.h b/system/host/fidl/include/fidl/ordinals.h
index 7aab3c5..60b0775 100644
--- a/system/host/fidl/include/fidl/ordinals.h
+++ b/system/host/fidl/include/fidl/ordinals.h
@@ -13,19 +13,21 @@
// Returns the Selector. If the Selector attribute is present, the
// function returns its value; otherwise, it returns the name parameter.
std::string GetSelector(const raw::AttributeList* attributes,
- SourceLocation name);
+ SourceLocation name);
-// Computes the ordinal for this method per the FIDL spec.
+// Computes the ordinal for this method.
//
// The ordinal value is equal to
+//
// *((int32_t *)sha256(library_name + "." + interface_name + "/" + method_name)) & 0x7fffffff;
+//
// If |method| has an Selector attribute, that value will be used as the
// method_name.
raw::Ordinal GetGeneratedOrdinal(const std::vector<StringView>& library_name,
const StringView& interface_name,
const raw::InterfaceMethod& method);
-// Retrieves the correct ordinal for this method per the FIDL spec.
+// Retrieves the correct ordinal for this method.
//
// If |method.ordinal| is not null, this method will return |method.ordinal|.
// Otherwise, the ordinal value is computed with GetGeneratedOrdinal.
@@ -33,6 +35,12 @@
const StringView& interface_name,
const raw::InterfaceMethod& method);
+// Retrieves the correct ordinal for |xunion_member|, following the same
+// algorithm as GetOrdinal() for interface methods above.
+raw::Ordinal GetOrdinal(const std::vector<StringView>& library_name,
+ const StringView& xunion_declaration_name,
+ const raw::XUnionMember& xunion_member);
+
} // namespace ordinals
} // namespace fidl
diff --git a/system/host/fidl/include/fidl/parser.h b/system/host/fidl/include/fidl/parser.h
index 6b8a55d..c92e3c2 100644
--- a/system/host/fidl/include/fidl/parser.h
+++ b/system/host/fidl/include/fidl/parser.h
@@ -180,7 +180,7 @@
std::unique_ptr<raw::TrueLiteral> ParseTrueLiteral();
std::unique_ptr<raw::FalseLiteral> ParseFalseLiteral();
std::unique_ptr<raw::Literal> ParseLiteral();
- std::unique_ptr<raw::Ordinal> ParseOrdinal();
+ std::unique_ptr<raw::Ordinal> MaybeParseOrdinal();
std::unique_ptr<raw::Constant> ParseConstant();
@@ -226,6 +226,10 @@
std::unique_ptr<raw::UnionDeclaration>
ParseUnionDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope&);
+ std::unique_ptr<raw::XUnionMember> ParseXUnionMember();
+ std::unique_ptr<raw::XUnionDeclaration>
+ ParseXUnionDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope&);
+
std::unique_ptr<raw::File> ParseFile();
std::map<StringView, types::HandleSubtype> handle_subtype_table_;
diff --git a/system/host/fidl/include/fidl/raw_ast.h b/system/host/fidl/include/fidl/raw_ast.h
index b845646..8ebe8ad 100644
--- a/system/host/fidl/include/fidl/raw_ast.h
+++ b/system/host/fidl/include/fidl/raw_ast.h
@@ -533,6 +533,34 @@
std::vector<std::unique_ptr<UnionMember>> members;
};
+class XUnionMember : public SourceElement {
+public:
+ XUnionMember(SourceElement const& element, std::unique_ptr<Type> type, std::unique_ptr<Identifier> identifier,
+ std::unique_ptr<AttributeList> attributes)
+ : SourceElement(element), type(std::move(type)), identifier(std::move(identifier)), attributes(std::move(attributes)) {}
+
+ void Accept(TreeVisitor& visitor);
+
+ std::unique_ptr<Type> type;
+ std::unique_ptr<Identifier> identifier;
+ std::unique_ptr<AttributeList> attributes;
+};
+
+class XUnionDeclaration : public SourceElement {
+public:
+ XUnionDeclaration(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
+ std::unique_ptr<Identifier> identifier,
+ std::vector<std::unique_ptr<XUnionMember>> members)
+ : SourceElement(element), attributes(std::move(attributes)), identifier(std::move(identifier)),
+ members(std::move(members)) {}
+
+ void Accept(TreeVisitor& visitor);
+
+ std::unique_ptr<AttributeList> attributes;
+ std::unique_ptr<Identifier> identifier;
+ std::vector<std::unique_ptr<XUnionMember>> members;
+};
+
class File : public SourceElement {
public:
File(SourceElement const& element, Token end,
@@ -544,7 +572,8 @@
std::vector<std::unique_ptr<InterfaceDeclaration>> interface_declaration_list,
std::vector<std::unique_ptr<StructDeclaration>> struct_declaration_list,
std::vector<std::unique_ptr<TableDeclaration>> table_declaration_list,
- std::vector<std::unique_ptr<UnionDeclaration>> union_declaration_list)
+ std::vector<std::unique_ptr<UnionDeclaration>> union_declaration_list,
+ std::vector<std::unique_ptr<XUnionDeclaration>> xunion_declaration_list)
: SourceElement(element),
attributes(std::move(attributes)),
library_name(std::move(library_name)),
@@ -555,6 +584,7 @@
struct_declaration_list(std::move(struct_declaration_list)),
table_declaration_list(std::move(table_declaration_list)),
union_declaration_list(std::move(union_declaration_list)),
+ xunion_declaration_list(std::move(xunion_declaration_list)),
end_(end) {}
void Accept(TreeVisitor& visitor);
@@ -568,6 +598,7 @@
std::vector<std::unique_ptr<StructDeclaration>> struct_declaration_list;
std::vector<std::unique_ptr<TableDeclaration>> table_declaration_list;
std::vector<std::unique_ptr<UnionDeclaration>> union_declaration_list;
+ std::vector<std::unique_ptr<XUnionDeclaration>> xunion_declaration_list;
Token end_;
};
diff --git a/system/host/fidl/include/fidl/tables_generator.h b/system/host/fidl/include/fidl/tables_generator.h
index f38f0ca..9b67ed9 100644
--- a/system/host/fidl/include/fidl/tables_generator.h
+++ b/system/host/fidl/include/fidl/tables_generator.h
@@ -48,6 +48,7 @@
void Generate(const coded::StructType& struct_type);
void Generate(const coded::TableType& table_type);
void Generate(const coded::UnionType& union_type);
+ void Generate(const coded::XUnionType& xunion_type);
void Generate(const coded::MessageType& message_type);
void Generate(const coded::HandleType& handle_type);
void Generate(const coded::InterfaceHandleType& interface_type);
@@ -59,14 +60,17 @@
void Generate(const coded::Type* type);
void Generate(const coded::StructField& field);
void Generate(const coded::TableField& field);
+ void Generate(const coded::XUnionField& field);
void GeneratePointerIfNeeded(const coded::StructType& struct_type);
void GeneratePointerIfNeeded(const coded::TableType& table_type);
void GeneratePointerIfNeeded(const coded::UnionType& union_type);
+ void GeneratePointerIfNeeded(const coded::XUnionType& xunion_type);
void GenerateForward(const coded::StructType& struct_type);
void GenerateForward(const coded::TableType& table_type);
void GenerateForward(const coded::UnionType& union_type);
+ void GenerateForward(const coded::XUnionType& xunion_type);
// Returns a pointer owned by coded_types_.
const coded::Type* CompileType(const flat::Type* type);
diff --git a/system/host/fidl/include/fidl/token_definitions.inc b/system/host/fidl/include/fidl/token_definitions.inc
index 910666f..a9cb6aa 100644
--- a/system/host/fidl/include/fidl/token_definitions.inc
+++ b/system/host/fidl/include/fidl/token_definitions.inc
@@ -61,6 +61,7 @@
KEYWORD(Struct, "struct")
KEYWORD(Table, "table")
KEYWORD(Union, "union")
+KEYWORD(XUnion, "xunion")
KEYWORD(True, "true")
KEYWORD(False, "false")
diff --git a/system/host/fidl/include/fidl/tree_visitor.h b/system/host/fidl/include/fidl/tree_visitor.h
index e5066f2..c901983 100644
--- a/system/host/fidl/include/fidl/tree_visitor.h
+++ b/system/host/fidl/include/fidl/tree_visitor.h
@@ -211,6 +211,12 @@
virtual void OnUnionDeclaration(std::unique_ptr<UnionDeclaration> const& element) {
element->Accept(*this);
}
+ virtual void OnXUnionMember(std::unique_ptr<XUnionMember> const& element) {
+ element->Accept(*this);
+ }
+ virtual void OnXUnionDeclaration(std::unique_ptr<XUnionDeclaration> const& element) {
+ element->Accept(*this);
+ }
virtual void OnFile(std::unique_ptr<File> const& element) {
element->Accept(*this);
}
diff --git a/system/host/fidl/include/fidl/type_shape.h b/system/host/fidl/include/fidl/type_shape.h
index fa0c87a..dfd369b 100644
--- a/system/host/fidl/include/fidl/type_shape.h
+++ b/system/host/fidl/include/fidl/type_shape.h
@@ -39,7 +39,7 @@
: FieldShape(TypeShape()) {}
TypeShape& Typeshape() { return typeshape_; }
- TypeShape Typeshape() const { return typeshape_; }
+ const TypeShape& Typeshape() const { return typeshape_; }
uint32_t Size() const { return typeshape_.Size(); }
uint32_t Alignment() const { return typeshape_.Alignment(); }
diff --git a/system/host/fidl/lib/c_generator.cpp b/system/host/fidl/lib/c_generator.cpp
index b4f5f54..e90fd6c 100644
--- a/system/host/fidl/lib/c_generator.cpp
+++ b/system/host/fidl/lib/c_generator.cpp
@@ -46,15 +46,15 @@
}
CGenerator::Member EmptyStructMember() {
- return {
- .kind = flat::Type::Kind::kPrimitive,
- .type = NamePrimitiveCType(types::PrimitiveSubtype::kUint8),
+ return {
+ .kind = flat::Type::Kind::kPrimitive,
+ .type = NamePrimitiveCType(types::PrimitiveSubtype::kUint8),
- // Prepend the reserved uint8_t field with a single underscore, which is
- // for reserved identifiers (see ISO C standard, section 7.1.3
- // <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf>).
- .name = "_reserved",
- };
+ // Prepend the reserved uint8_t field with a single underscore, which is
+ // for reserved identifiers (see ISO C standard, section 7.1.3
+ // <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf>).
+ .name = "_reserved",
+ };
}
CGenerator::Transport ParseTransport(StringView view) {
@@ -137,6 +137,7 @@
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion:
switch (member.nullability) {
case types::Nullability::kNullable:
*file << "const " << member.type << " " << member.name;
@@ -186,6 +187,7 @@
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion:
switch (member.nullability) {
case types::Nullability::kNullable:
*file << member.type << " out_" << member.name;
@@ -257,7 +259,7 @@
return true;
if (member.kind == flat::Type::Kind::kIdentifier) {
return member.nullability == types::Nullability::kNullable &&
- (member.decl_kind == flat::Decl::Kind::kStruct || member.decl_kind == flat::Decl::Kind::kUnion);
+ (member.decl_kind == flat::Decl::Kind::kStruct || member.decl_kind == flat::Decl::Kind::kUnion || member.decl_kind == flat::Decl::Kind::kXUnion);
}
return false;
}
@@ -277,7 +279,8 @@
void EmitParameterSizeValidation(std::ostream* file,
const std::vector<CGenerator::Member>& params) {
for (const auto& member : params) {
- if (member.max_num_elements == std::numeric_limits<uint32_t>::max()) continue;
+ if (member.max_num_elements == std::numeric_limits<uint32_t>::max())
+ continue;
std::string param_name;
if (member.kind == flat::Type::Kind::kVector) {
param_name = member.name + "_count";
@@ -287,7 +290,7 @@
assert(false && "only vector/string has size limit");
}
*file << kIndent
- << "if (" << param_name << " > " << member.max_num_elements << ") {\n";
+ << "if (" << param_name << " > " << member.max_num_elements << ") {\n";
*file << kIndent << kIndent << "return ZX_ERR_INVALID_ARGS;\n";
*file << kIndent << "}\n";
}
@@ -380,6 +383,9 @@
case flat::Decl::Kind::kTable:
assert(false && "c-codegen for tables not yet implemented");
break;
+ case flat::Decl::Kind::kXUnion:
+ assert(false && "c-codegen for extensible unions not yet implemented");
+ break;
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kUnion:
switch (member.nullability) {
@@ -561,6 +567,17 @@
return members;
}
+std::vector<CGenerator::Member>
+GenerateMembers(const flat::Library* library,
+ const std::vector<flat::XUnion::Member>& xunion_members) {
+ std::vector<CGenerator::Member> members;
+ members.reserve(xunion_members.size());
+ for (const auto& xunion_member : xunion_members) {
+ members.push_back(CreateMember(library, xunion_member));
+ }
+ return members;
+}
+
void GetMethodParameters(const flat::Library* library,
const CGenerator::NamedMethod& method_info,
std::vector<CGenerator::Member>* request,
@@ -698,6 +715,11 @@
file_ << "};\n";
}
+void CGenerator::GenerateTaggedXUnionDeclaration(StringView name,
+ const std::vector<Member>& members) {
+ // XUnions are (intentionally) unimplemented for C bindings.
+}
+
// TODO(TO-702) These should maybe check for global name
// collisions? Otherwise, is there some other way they should fail?
std::map<const flat::Decl*, CGenerator::NamedConst>
@@ -807,6 +829,16 @@
return named_unions;
}
+std::map<const flat::Decl*, CGenerator::NamedXUnion>
+CGenerator::NameXUnions(const std::vector<std::unique_ptr<flat::XUnion>>& xunion_infos) {
+ std::map<const flat::Decl*, NamedXUnion> named_xunions;
+ for (const auto& xunion_info : xunion_infos) {
+ std::string xunion_name = NameName(xunion_info->name, "_", "_");
+ named_xunions.emplace(xunion_info.get(), NamedXUnion{std::move(xunion_name), *xunion_info});
+ }
+ return named_xunions;
+}
+
void CGenerator::ProduceConstForwardDeclaration(const NamedConst& named_const) {
// TODO(TO-702)
}
@@ -853,6 +885,10 @@
GenerateStructTypedef(named_union.name);
}
+void CGenerator::ProduceXUnionForwardDeclaration(const NamedXUnion& named_xunion) {
+ GenerateStructTypedef(named_xunion.name);
+}
+
void CGenerator::ProduceInterfaceExternDeclaration(const NamedInterface& named_interface) {
for (const auto& method_info : named_interface.methods) {
if (method_info.request)
@@ -943,6 +979,24 @@
EmitBlank(&file_);
}
+void CGenerator::ProduceXUnionDeclaration(const NamedXUnion& named_xunion) {
+ std::vector<CGenerator::Member> members =
+ GenerateMembers(library_, named_xunion.xunion_info.members);
+ GenerateTaggedXUnionDeclaration(named_xunion.name, members);
+
+ uint32_t tag = 0u;
+ for (const auto& member : named_xunion.xunion_info.members) {
+ std::string tag_name = NameXUnionTag(named_xunion.name, member);
+ auto xunion_tag_type = types::PrimitiveSubtype::kUint32;
+ std::ostringstream value;
+ value << tag;
+ GenerateIntegerDefine(std::move(tag_name), xunion_tag_type, value.str());
+ ++tag;
+ }
+
+ EmitBlank(&file_);
+}
+
void CGenerator::ProduceInterfaceClientDeclaration(const NamedInterface& named_interface) {
for (const auto& method_info : named_interface.methods) {
if (!method_info.request)
@@ -1158,6 +1212,9 @@
case flat::Decl::Kind::kTable:
assert(false && "c-codegen for tables not yet implemented");
break;
+ case flat::Decl::Kind::kXUnion:
+ assert(false && "c-codegen for extensible unions not yet implemented");
+ break;
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kUnion:
switch (member.nullability) {
@@ -1273,6 +1330,9 @@
case flat::Decl::Kind::kTable:
assert(false && "c-codegen for tables not yet implemented");
break;
+ case flat::Decl::Kind::kXUnion:
+ assert(false && "c-codegen for extensible unions not yet implemented");
+ break;
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kUnion:
switch (member.nullability) {
@@ -1380,6 +1440,8 @@
NameTables(library_->table_declarations_);
std::map<const flat::Decl*, NamedUnion> named_unions =
NameUnions(library_->union_declarations_);
+ std::map<const flat::Decl*, NamedXUnion> named_xunions =
+ NameXUnions(library_->xunion_declarations_);
file_ << "\n// Forward declarations\n\n";
@@ -1427,6 +1489,13 @@
}
break;
}
+ case flat::Decl::Kind::kXUnion: {
+ auto iter = named_xunions.find(decl);
+ if (iter != named_xunions.end()) {
+ ProduceXUnionForwardDeclaration(iter->second);
+ }
+ break;
+ }
default:
abort();
}
@@ -1441,6 +1510,7 @@
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion:
// Only messages have extern fidl_type_t declarations.
break;
case flat::Decl::Kind::kInterface: {
@@ -1495,6 +1565,13 @@
}
break;
}
+ case flat::Decl::Kind::kXUnion: {
+ auto iter = named_xunions.find(decl);
+ if (iter != named_xunions.end()) {
+ ProduceXUnionDeclaration(iter->second);
+ }
+ break;
+ }
default:
abort();
}
@@ -1509,6 +1586,7 @@
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion:
// Only interfaces have client declarations.
break;
case flat::Decl::Kind::kInterface: {
@@ -1550,6 +1628,7 @@
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion:
// Only interfaces have client implementations.
break;
case flat::Decl::Kind::kInterface: {
@@ -1587,6 +1666,7 @@
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion:
// Only interfaces have client implementations.
break;
case flat::Decl::Kind::kInterface: {
diff --git a/system/host/fidl/lib/flat_ast.cpp b/system/host/fidl/lib/flat_ast.cpp
index daf54bd..7ef4253 100644
--- a/system/host/fidl/lib/flat_ast.cpp
+++ b/system/host/fidl/lib/flat_ast.cpp
@@ -19,6 +19,8 @@
#include "fidl/raw_ast.h"
#include "fidl/utils.h"
+#include "zircon/fidl.h"
+
namespace fidl {
namespace flat {
@@ -28,8 +30,8 @@
class ScopeInsertResult {
public:
- explicit ScopeInsertResult(std::unique_ptr<SourceLocation> previous_occurance)
- : previous_occurance_(std::move(previous_occurance)) {}
+ explicit ScopeInsertResult(std::unique_ptr<SourceLocation> previous_occurrence)
+ : previous_occurrence_(std::move(previous_occurrence)) {}
static ScopeInsertResult Ok() { return ScopeInsertResult(nullptr); }
static ScopeInsertResult FailureAt(SourceLocation previous) {
@@ -37,16 +39,16 @@
}
bool ok() const {
- return previous_occurance_ == nullptr;
+ return previous_occurrence_ == nullptr;
}
- const SourceLocation& previous_occurance() const {
+ const SourceLocation& previous_occurrence() const {
assert(!ok());
- return *previous_occurance_;
+ return *previous_occurrence_;
}
private:
- std::unique_ptr<SourceLocation> previous_occurance_;
+ std::unique_ptr<SourceLocation> previous_occurrence_;
};
template <typename T>
@@ -191,11 +193,11 @@
}
TypeShape FidlMessageTypeShape(std::vector<FieldShape*>* fields) {
- auto struct_shape = FidlStructTypeShape(fields);
+ auto struct_shape = FidlStructTypeShape(fields);
return AlignTypeshape(struct_shape, kMessageAlign);
}
-TypeShape PointerTypeShape(TypeShape element, uint32_t max_element_count = 1u) {
+TypeShape PointerTypeShape(const TypeShape& element, uint32_t max_element_count = 1u) {
// Because FIDL supports recursive data structures, we might not have
// computed the TypeShape for the element we're pointing to. In that case,
// the size will be zero and we'll use |numeric_limits<uint32_t>::max()| as
@@ -222,7 +224,7 @@
return TypeShape(8u, 8u, depth, max_handles, max_out_of_line);
}
-TypeShape CEnvelopeTypeShape(TypeShape contained_type) {
+TypeShape CEnvelopeTypeShape(const TypeShape& contained_type) {
auto packed_sizes_field = FieldShape(kUint64TypeShape);
auto pointer_type = FieldShape(PointerTypeShape(contained_type));
std::vector<FieldShape*> header{&packed_sizes_field, &pointer_type};
@@ -253,6 +255,22 @@
return CStructTypeShape(&header, extra_handles);
}
+TypeShape CXUnionTypeShape(const std::vector<flat::XUnion::Member>& members, uint32_t extra_handles = 0u) {
+ uint32_t depth = 0u;
+ uint32_t max_handles = 0u;
+ uint32_t max_out_of_line = 0u;
+
+ for (const auto& member : members) {
+ const auto& envelope = CEnvelopeTypeShape(member.fieldshape.Typeshape());
+
+ depth = ClampedAdd(depth, envelope.Depth());
+ max_handles = ClampedAdd(max_handles, envelope.MaxHandles());
+ max_out_of_line = std::max(max_out_of_line, envelope.MaxOutOfLine());
+ }
+
+ return TypeShape(sizeof(fidl_xunion_t), 8u, depth, max_handles, max_out_of_line);
+}
+
TypeShape ArrayTypeShape(TypeShape element, uint32_t count) {
// TODO(FIDL-345): once TypeShape builders are done and methods can fail, do a
// __builtin_mul_overflow and fail on overflow instead of ClampedMultiply(element.Size(), count)
@@ -403,6 +421,12 @@
}
}
+Type* Typespace::CreateForwardDeclaredType(const flat::Name& name, types::Nullability nullability) {
+ // TODO(pascallouis): Implement :-).
+
+ return nullptr;
+}
+
bool NoOpConstraint(ErrorReporter* error_reporter,
const raw::Attribute* attribute,
const Decl* decl) {
@@ -412,9 +436,9 @@
AttributeSchema::AttributeSchema(const std::set<Placement>& allowed_placements,
const std::set<std::string> allowed_values,
Constraint constraint)
- : allowed_placements_(allowed_placements),
- allowed_values_(allowed_values),
- constraint_(std::move(constraint)) {}
+ : allowed_placements_(allowed_placements),
+ allowed_values_(allowed_values),
+ constraint_(std::move(constraint)) {}
void AttributeSchema::ValidatePlacement(ErrorReporter* error_reporter,
const raw::Attribute* attribute,
@@ -517,24 +541,29 @@
return false;
uint32_t max_bytes = std::numeric_limits<uint32_t>::max();
switch (decl->kind) {
- case Decl::Kind::kStruct: {
- auto struct_decl = static_cast<const Struct*>(decl);
- max_bytes = struct_decl->typeshape.Size() + struct_decl->typeshape.MaxOutOfLine();
- break;
- }
- case Decl::Kind::kTable: {
- auto table_decl = static_cast<const Table*>(decl);
- max_bytes = table_decl->typeshape.Size() + table_decl->typeshape.MaxOutOfLine();
- break;
- }
- case Decl::Kind::kUnion: {
- auto union_decl = static_cast<const Union*>(decl);
- max_bytes = union_decl->typeshape.Size() + union_decl->typeshape.MaxOutOfLine();
- break;
- }
- default:
- assert(false && "unexpected kind");
- return false;
+ case Decl::Kind::kStruct: {
+ auto struct_decl = static_cast<const Struct*>(decl);
+ max_bytes = struct_decl->typeshape.Size() + struct_decl->typeshape.MaxOutOfLine();
+ break;
+ }
+ case Decl::Kind::kTable: {
+ auto table_decl = static_cast<const Table*>(decl);
+ max_bytes = table_decl->typeshape.Size() + table_decl->typeshape.MaxOutOfLine();
+ break;
+ }
+ case Decl::Kind::kUnion: {
+ auto union_decl = static_cast<const Union*>(decl);
+ max_bytes = union_decl->typeshape.Size() + union_decl->typeshape.MaxOutOfLine();
+ break;
+ }
+ case Decl::Kind::kXUnion: {
+ auto xunion_decl = static_cast<const XUnion*>(decl);
+ max_bytes = xunion_decl->typeshape.Size() + xunion_decl->typeshape.MaxOutOfLine();
+ break;
+ }
+ default:
+ assert(false && "unexpected kind");
+ return false;
}
if (max_bytes > bound) {
std::ostringstream message;
@@ -557,24 +586,29 @@
return false;
uint32_t max_handles = std::numeric_limits<uint32_t>::max();
switch (decl->kind) {
- case Decl::Kind::kStruct: {
- auto struct_decl = static_cast<const Struct*>(decl);
- max_handles = struct_decl->typeshape.MaxHandles();
- break;
- }
- case Decl::Kind::kTable: {
- auto table_decl = static_cast<const Table*>(decl);
- max_handles = table_decl->typeshape.MaxHandles();
- break;
- }
- case Decl::Kind::kUnion: {
- auto union_decl = static_cast<const Union*>(decl);
- max_handles = union_decl->typeshape.MaxHandles();
- break;
- }
- default:
- assert(false && "unexpected kind");
- return false;
+ case Decl::Kind::kStruct: {
+ auto struct_decl = static_cast<const Struct*>(decl);
+ max_handles = struct_decl->typeshape.MaxHandles();
+ break;
+ }
+ case Decl::Kind::kTable: {
+ auto table_decl = static_cast<const Table*>(decl);
+ max_handles = table_decl->typeshape.MaxHandles();
+ break;
+ }
+ case Decl::Kind::kUnion: {
+ auto union_decl = static_cast<const Union*>(decl);
+ max_handles = union_decl->typeshape.MaxHandles();
+ break;
+ }
+ case Decl::Kind::kXUnion: {
+ auto xunion_decl = static_cast<const XUnion*>(decl);
+ max_handles = xunion_decl->typeshape.MaxHandles();
+ break;
+ }
+ default:
+ assert(false && "unexpected kind");
+ return false;
}
if (max_handles > bound) {
std::ostringstream message;
@@ -590,6 +624,7 @@
}
Libraries::Libraries() {
+ // clang-format off
AddAttributeSchema("Discoverable", AttributeSchema({
AttributeSchema::Placement::kInterfaceDecl,
}, {
@@ -617,6 +652,7 @@
AttributeSchema::Placement::kStructDecl,
AttributeSchema::Placement::kTableDecl,
AttributeSchema::Placement::kUnionDecl,
+ AttributeSchema::Placement::kXUnionDecl,
}, {
/* any value */
},
@@ -627,12 +663,14 @@
AttributeSchema::Placement::kStructDecl,
AttributeSchema::Placement::kTableDecl,
AttributeSchema::Placement::kUnionDecl,
+ AttributeSchema::Placement::kXUnionDecl,
}, {
/* any value */
},
MaxHandlesConstraint));
AddAttributeSchema("Selector", AttributeSchema({
AttributeSchema::Placement::kMethod,
+ AttributeSchema::Placement::kXUnionMember,
}, {
/* any value */
}));
@@ -643,6 +681,7 @@
"SocketControl",
"OvernetStream",
}));
+ // clang-format on
}
bool Libraries::Insert(std::unique_ptr<Library> library) {
@@ -665,8 +704,8 @@
size_t EditDistance(const std::string& sequence1, const std::string& sequence2) {
size_t s1_length = sequence1.length();
size_t s2_length = sequence2.length();
- size_t row1[s1_length+1];
- size_t row2[s1_length+1];
+ size_t row1[s1_length + 1];
+ size_t row2[s1_length + 1];
size_t* last_row = row1;
size_t* this_row = row2;
for (size_t i = 0; i <= s1_length; i++)
@@ -677,7 +716,8 @@
for (size_t i = 1; i <= s1_length; i++) {
auto s1c = sequence1[i - 1];
this_row[i] = std::min(std::min(
- last_row[i] + 1, this_row[i - 1] + 1), last_row[i - 1] + (s1c == s2c ? 0 : 1));
+ last_row[i] + 1, this_row[i - 1] + 1),
+ last_row[i - 1] + (s1c == s2c ? 0 : 1));
}
std::swap(last_row, this_row);
}
@@ -1244,6 +1284,31 @@
return RegisterDecl(union_declarations_.back().get());
}
+bool Library::ConsumeXUnionDeclaration(std::unique_ptr<raw::XUnionDeclaration> xunion_declaration) {
+ auto name = Name(this, xunion_declaration->identifier->location());
+
+ std::vector<XUnion::Member> members;
+ for (auto& member : xunion_declaration->members) {
+ std::unique_ptr<raw::Ordinal> ordinal =
+ std::make_unique<raw::Ordinal>(fidl::ordinals::GetOrdinal(library_name_, name.name_part(), *member));
+
+ auto location = member->identifier->location();
+ std::unique_ptr<Type> type;
+ if (!ConsumeType(std::move(member->type), location, &type))
+ return false;
+
+ if (type->nullability != types::Nullability::kNonnullable) {
+ return Fail(member->location(), "Extensible union members cannot be nullable");
+ }
+
+ members.emplace_back(std::move(ordinal), std::move(type), location, std::move(member->attributes));
+ }
+
+ xunion_declarations_.push_back(
+ std::make_unique<XUnion>(std::move(xunion_declaration->attributes), std::move(name), std::move(members)));
+ return RegisterDecl(xunion_declarations_.back().get());
+}
+
bool Library::ConsumeFile(std::unique_ptr<raw::File> file) {
if (file->attributes) {
ValidateAttributesPlacement(AttributeSchema::Placement::kLibrary, file->attributes.get());
@@ -1323,6 +1388,13 @@
}
}
+ auto xunion_declaration_list = std::move(file->xunion_declaration_list);
+ for (auto& xunion_declaration : xunion_declaration_list) {
+ if (!ConsumeXUnionDeclaration(std::move(xunion_declaration))) {
+ return false;
+ }
+ }
+
return true;
}
@@ -1762,8 +1834,8 @@
// of D1 before the declaration of D2. For instance, given the fidl
// struct D2 { D1 d; };
// struct D1 { int32 x; };
-// D1 has an edge pointing to D2. Note that struct and union pointers,
-// unlike inline structs or unions, do not have dependency edges.
+// D1 has an edge pointing to D2. Note that struct, union, and xunion pointers,
+// unlike inline structs/unions/xunions, do not have dependency edges.
bool Library::DeclDependencies(Decl* decl, std::set<Decl*>* out_edges) {
std::set<Decl*> edges;
auto maybe_add_decl = [this, &edges](const Type* type, LookupOption option) {
@@ -1858,6 +1930,13 @@
}
break;
}
+ case Decl::Kind::kXUnion: {
+ auto xunion_decl = static_cast<const XUnion*>(decl);
+ for (const auto& member : xunion_decl->members) {
+ maybe_add_decl(member.type.get(), LookupOption::kIgnoreNullable);
+ }
+ break;
+ }
}
*out_edges = std::move(edges);
return true;
@@ -2073,7 +2152,7 @@
if (!name_result.ok())
return Fail(method.name,
"Multiple methods with the same name in an interface; last occurrence was at " +
- name_result.previous_occurance().position());
+ name_result.previous_occurrence().position());
auto ordinal_result = method_scope.ordinals.Insert(method.ordinal->value, method.name);
if (method.ordinal->value == 0)
return Fail(method.ordinal->location(), "Ordinal value 0 disallowed.");
@@ -2083,7 +2162,7 @@
replacement_method.push_back('_');
return Fail(method.ordinal->location(),
"Multiple methods with the same ordinal in an interface; previous was at " +
- ordinal_result.previous_occurance().position() + ". If these " +
+ ordinal_result.previous_occurrence().position() + ". If these " +
"were automatically generated, consider using attribute " +
"[Selector=\"" + replacement_method + "\"] to change the " +
"name used to calculate the ordinal.");
@@ -2179,7 +2258,7 @@
if (!name_result.ok())
return Fail(member.name,
"Multiple struct fields with the same name; previous was at " +
- name_result.previous_occurance().position());
+ name_result.previous_occurrence().position());
if (!CompileType(member.type.get(), &member.fieldshape.Typeshape()))
return false;
fidl_struct.push_back(&member.fieldshape);
@@ -2225,13 +2304,13 @@
if (!ordinal_result.ok())
return Fail(member.ordinal->location(),
"Multiple table fields with the same ordinal; previous was at " +
- ordinal_result.previous_occurance().position());
+ ordinal_result.previous_occurrence().position());
if (member.maybe_used) {
auto name_result = name_scope.Insert(member.maybe_used->name.data(), member.maybe_used->name);
if (!name_result.ok())
return Fail(member.maybe_used->name,
"Multiple table fields with the same name; previous was at " +
- name_result.previous_occurance().position());
+ name_result.previous_occurrence().position());
if (!CompileType(member.maybe_used->type.get(), &member.maybe_used->typeshape))
return false;
}
@@ -2292,7 +2371,7 @@
if (!name_result.ok())
return Fail(member.name,
"Multiple union members with the same name; previous was at " +
- name_result.previous_occurance().position());
+ name_result.previous_occurrence().position());
if (!CompileType(member.type.get(), &member.fieldshape.Typeshape()))
return false;
}
@@ -2333,6 +2412,58 @@
return true;
}
+bool Library::CompileXUnion(XUnion* xunion_declaration) {
+ Compiling guard(xunion_declaration);
+ Scope<StringView> scope;
+ Scope<uint32_t> ordinal_scope;
+
+ for (auto& member : xunion_declaration->members) {
+ auto ordinal_result = ordinal_scope.Insert(member.ordinal->value, member.ordinal->location());
+ if (!ordinal_result.ok())
+ return Fail(member.ordinal->location(),
+ "Multiple xunion fields with the same ordinal; previous was at " +
+ ordinal_result.previous_occurrence().position());
+
+ auto name_result = scope.Insert(member.name.data(), member.name);
+ if (!name_result.ok())
+ return Fail(member.name,
+ "Multiple xunion members with the same name; previous was at " +
+ name_result.previous_occurrence().position());
+
+ if (!CompileType(member.type.get(), &member.fieldshape.Typeshape()))
+ return false;
+ }
+
+ uint32_t max_member_handles;
+ if (xunion_declaration->recursive) {
+ max_member_handles = std::numeric_limits<uint32_t>::max();
+ } else {
+ // Member handles will be counted by CXUnionTypeShape.
+ max_member_handles = 0u;
+ }
+
+ xunion_declaration->typeshape = CXUnionTypeShape(xunion_declaration->members, max_member_handles);
+
+ auto placement_ok = error_reporter_->Checkpoint();
+ // Attributes: check placement.
+ ValidateAttributesPlacement(
+ AttributeSchema::Placement::kXUnionDecl,
+ xunion_declaration->attributes.get());
+ for (const auto& member : xunion_declaration->members) {
+ ValidateAttributesPlacement(
+ AttributeSchema::Placement::kXUnionMember,
+ member.attributes.get());
+ }
+ if (placement_ok.NoNewErrors()) {
+ // Attributes: check constraint.
+ ValidateAttributesConstraints(
+ xunion_declaration,
+ xunion_declaration->attributes.get());
+ }
+
+ return true;
+}
+
bool Library::CompileLibraryName() {
const std::regex pattern("^[a-z][a-z0-9]*$");
for (const auto& part_view : library_name_) {
@@ -2405,6 +2536,13 @@
}
break;
}
+ case Decl::Kind::kXUnion: {
+ auto xunion_decl = static_cast<XUnion*>(decl);
+ if (!CompileXUnion(xunion_decl)) {
+ return false;
+ }
+ break;
+ }
default:
abort();
}
@@ -2566,6 +2704,22 @@
typeshape = PointerTypeShape(typeshape);
break;
}
+ case Decl::Kind::kXUnion: {
+ XUnion* xunion_decl = static_cast<XUnion*>(named_decl);
+ if (!xunion_decl->compiled) {
+ if (xunion_decl->compiling) {
+ xunion_decl->recursive = true;
+ } else {
+ if (!CompileXUnion(xunion_decl)) {
+ return false;
+ }
+ }
+ }
+ typeshape = xunion_decl->typeshape;
+ if (identifier_type->nullability == types::Nullability::kNullable)
+ typeshape = PointerTypeShape(typeshape);
+ break;
+ }
default: {
abort();
}
@@ -2651,7 +2805,7 @@
std::ostringstream msg_stream;
msg_stream << "value of member " << name;
msg_stream << " conflicts with previously declared member ";
- msg_stream << NameIdentifier(value_result.previous_occurance()) << " in the enum ";
+ msg_stream << NameIdentifier(value_result.previous_occurrence()) << " in the enum ";
msg_stream << enum_decl->GetName();
// We can log the error and then continue validating other members for other bugs
diff --git a/system/host/fidl/lib/json_generator.cpp b/system/host/fidl/lib/json_generator.cpp
index 071c0af..f14b150 100644
--- a/system/host/fidl/lib/json_generator.cpp
+++ b/system/host/fidl/lib/json_generator.cpp
@@ -526,6 +526,33 @@
});
}
+void JSONGenerator::Generate(const flat::XUnion& value) {
+ GenerateObject([&]() {
+ GenerateObjectMember("name", value.name, Position::kFirst);
+ if (value.attributes)
+ GenerateObjectMember("maybe_attributes", value.attributes);
+ GenerateObjectMember("members", value.members);
+ GenerateObjectMember("size", value.typeshape.Size());
+ GenerateObjectMember("max_out_of_line", value.typeshape.MaxOutOfLine());
+ GenerateObjectMember("alignment", value.typeshape.Alignment());
+ GenerateObjectMember("max_handles", value.typeshape.MaxHandles());
+ });
+}
+
+void JSONGenerator::Generate(const flat::XUnion::Member& value) {
+ GenerateObject([&]() {
+ GenerateObjectMember("ordinal", value.ordinal, Position::kFirst);
+ GenerateObjectMember("type", value.type);
+ GenerateObjectMember("name", value.name);
+ if (value.attributes)
+ GenerateObjectMember("maybe_attributes", value.attributes);
+ GenerateObjectMember("size", value.fieldshape.Size());
+ GenerateObjectMember("max_out_of_line", value.fieldshape.MaxOutOfLine());
+ GenerateObjectMember("alignment", value.fieldshape.Alignment());
+ GenerateObjectMember("offset", value.fieldshape.Offset());
+ });
+}
+
void JSONGenerator::Generate(const flat::Library* library) {
GenerateObject([&]() {
auto library_name = flat::LibraryName(library, ".");
@@ -568,6 +595,9 @@
for (const auto& decl : library->union_declarations_)
GenerateDeclarationsEntry(count++, decl->name, "union");
+
+ for (const auto& decl : library->xunion_declarations_)
+ GenerateDeclarationsEntry(count++, decl->name, "xunion");
});
}
@@ -595,6 +625,7 @@
GenerateObjectMember("struct_declarations", library_->struct_declarations_);
GenerateObjectMember("table_declarations", library_->table_declarations_);
GenerateObjectMember("union_declarations", library_->union_declarations_);
+ GenerateObjectMember("xunion_declarations", library_->xunion_declarations_);
// The library's declaration_order_ contains all the declarations for all
// transitive dependencies. The backend only needs the declaration order
diff --git a/system/host/fidl/lib/names.cpp b/system/host/fidl/lib/names.cpp
index 744533f..8fc78ea 100644
--- a/system/host/fidl/lib/names.cpp
+++ b/system/host/fidl/lib/names.cpp
@@ -255,6 +255,10 @@
return std::string(union_name) + "Tag_" + NameIdentifier(member.name);
}
+std::string NameXUnionTag(StringView xunion_name, const flat::XUnion::Member& member) {
+ return std::string(xunion_name) + "Tag_" + NameIdentifier(member.name);
+}
+
std::string NameFlatConstant(const flat::Constant* constant) {
switch (constant->kind) {
case flat::Constant::Kind::kLiteral: {
@@ -376,7 +380,8 @@
case flat::Decl::Kind::kEnum:
case flat::Decl::Kind::kStruct:
case flat::Decl::Kind::kTable:
- case flat::Decl::Kind::kUnion: {
+ case flat::Decl::Kind::kUnion:
+ case flat::Decl::Kind::kXUnion: {
std::string name = NameName(identifier_type->name, "_", "_");
if (identifier_type->nullability == types::Nullability::kNullable) {
name.push_back('*');
@@ -483,6 +488,10 @@
return NameName(union_decl->name, "_", "_");
}
+std::string NameCodedXUnion(const flat::XUnion* xunion_decl) {
+ return NameName(xunion_decl->name, "_", "_");
+}
+
std::string NameCodedHandle(types::HandleSubtype subtype, types::Nullability nullability) {
std::string name("Handle");
name += NameHandleSubtype(subtype);
diff --git a/system/host/fidl/lib/ordinals.cpp b/system/host/fidl/lib/ordinals.cpp
index 70d6b9c..3716459 100644
--- a/system/host/fidl/lib/ordinals.cpp
+++ b/system/host/fidl/lib/ordinals.cpp
@@ -12,7 +12,8 @@
namespace fidl {
namespace ordinals {
-std::string GetSelector(const raw::AttributeList* attributes, SourceLocation name) {
+std::string GetSelector(const raw::AttributeList* attributes,
+ SourceLocation name) {
if (attributes != nullptr) {
const size_t size = attributes->attributes.size();
for (int i = 0; i < size; i++) {
@@ -24,11 +25,27 @@
return std::string(name.data().data(), name.data().size());
}
-raw::Ordinal GetGeneratedOrdinal(
- const std::vector<StringView>& library_name,
- const StringView& interface_name,
- const raw::InterfaceMethod& method) {
- std::string method_name = GetSelector(method.attributes.get(), method.identifier->location());
+raw::Ordinal GetGeneratedOrdinal(const StringView& full_name,
+ const raw::SourceElement& source_element) {
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+ SHA256(reinterpret_cast<const uint8_t*>(full_name.data()), full_name.size(), digest);
+ // The following dance ensures that we treat the bytes as a little-endian
+ // int32 regardless of host byte order.
+ uint32_t ordinal = static_cast<uint32_t>(digest[0]) |
+ static_cast<uint32_t>(digest[1]) << 8 |
+ static_cast<uint32_t>(digest[2]) << 16 |
+ static_cast<uint32_t>(digest[3]) << 24;
+
+ ordinal &= 0x7fffffff;
+ return raw::Ordinal(source_element, ordinal);
+}
+
+raw::Ordinal GetGeneratedOrdinal(const std::vector<StringView>& library_name,
+ const StringView& container_name,
+ const raw::AttributeList* attributes,
+ SourceLocation name,
+ const raw::SourceElement& source_element) {
+ std::string method_name = GetSelector(attributes, name);
std::string full_name;
bool once = false;
for (StringView id : library_name) {
@@ -40,21 +57,17 @@
full_name.append(id.data(), id.size());
}
full_name.append(".");
- full_name.append(interface_name.data(), interface_name.size());
+ full_name.append(container_name.data(), container_name.size());
full_name.append("/");
full_name.append(method_name);
- uint8_t digest[SHA256_DIGEST_LENGTH];
- SHA256(reinterpret_cast<const uint8_t*>(full_name.data()), full_name.size(), digest);
- // The following dance ensures that we treat the bytes as a little-endian
- // int32 regardless of host byte order.
- uint32_t ordinal = static_cast<uint32_t>(digest[0]) |
- static_cast<uint32_t>(digest[1]) << 8 |
- static_cast<uint32_t>(digest[2]) << 16 |
- static_cast<uint32_t>(digest[3]) << 24;
+ return GetGeneratedOrdinal(StringView(full_name), source_element);
+}
- ordinal &= 0x7fffffff;
- return raw::Ordinal(*method.identifier, ordinal);
+raw::Ordinal GetGeneratedOrdinal(const std::vector<StringView>& library_name,
+ const StringView& interface_name,
+ const raw::InterfaceMethod& method) {
+ return GetGeneratedOrdinal(library_name, interface_name, method.attributes.get(), method.identifier->location(), method);
}
raw::Ordinal GetOrdinal(const std::vector<StringView>& library_name,
@@ -62,8 +75,17 @@
const raw::InterfaceMethod& method) {
if (method.ordinal != nullptr)
return *method.ordinal;
+
return GetGeneratedOrdinal(library_name, interface_name, method);
}
+raw::Ordinal GetOrdinal(const std::vector<StringView>& library_name,
+ const StringView& xunion_declaration_name,
+ const raw::XUnionMember& xunion_member) {
+ // Note that this ordinal hashing for xunion members uses the same ordinal
+ // hashing algorithm as for FIDL methods, which results in 31 bits, not 32.
+ return GetGeneratedOrdinal(library_name, xunion_declaration_name, xunion_member.attributes.get(), xunion_member.identifier->location(), xunion_member);
+}
+
} // namespace ordinals
} // namespace fidl
diff --git a/system/host/fidl/lib/parser.cpp b/system/host/fidl/lib/parser.cpp
index eabed11..feb592a 100644
--- a/system/host/fidl/lib/parser.cpp
+++ b/system/host/fidl/lib/parser.cpp
@@ -4,8 +4,8 @@
#include <errno.h>
-#include "fidl/parser.h"
#include "fidl/attributes.h"
+#include "fidl/parser.h"
namespace fidl {
@@ -146,7 +146,7 @@
return std::make_unique<raw::NumericLiteral>(scope.GetSourceElement());
}
-std::unique_ptr<raw::Ordinal> Parser::ParseOrdinal() {
+std::unique_ptr<raw::Ordinal> Parser::MaybeParseOrdinal() {
ASTScope scope(this);
if (Peek().kind() != Token::Kind::kNumericLiteral) {
@@ -683,7 +683,7 @@
}
std::unique_ptr<raw::InterfaceMethod> Parser::ParseInterfaceMethod(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
- auto ordinal = ParseOrdinal();
+ auto ordinal = MaybeParseOrdinal();
if (!Ok())
return Fail();
@@ -875,7 +875,7 @@
if (!Ok())
return Fail();
- auto ordinal = ParseOrdinal();
+ auto ordinal = MaybeParseOrdinal();
if (!Ok())
return Fail();
@@ -1014,6 +1014,75 @@
std::move(members));
}
+std::unique_ptr<raw::XUnionMember> Parser::ParseXUnionMember() {
+ ASTScope scope(this);
+
+ auto attributes = MaybeParseAttributeList();
+ if (!Ok())
+ return Fail();
+
+ auto type = ParseType();
+ if (!Ok())
+ return Fail();
+
+ auto identifier = ParseIdentifier();
+ if (!Ok())
+ return Fail();
+
+ return std::make_unique<raw::XUnionMember>(scope.GetSourceElement(),
+ std::move(type),
+ std::move(identifier),
+ std::move(attributes));
+}
+
+std::unique_ptr<raw::XUnionDeclaration>
+Parser::ParseXUnionDeclaration(std::unique_ptr<raw::AttributeList> attributes, ASTScope& scope) {
+ std::vector<std::unique_ptr<raw::XUnionMember>> members;
+
+ ConsumeToken(IdentifierOfSubkind(Token::Subkind::kXUnion));
+ if (!Ok())
+ return Fail();
+
+ auto identifier = ParseIdentifier();
+ if (!Ok())
+ return Fail();
+
+ ConsumeToken(OfKind(Token::Kind::kLeftCurly));
+ if (!Ok())
+ return Fail();
+
+ auto parse_member = [&]() {
+ switch (Peek().combined()) {
+ default:
+ ConsumeToken(OfKind(Token::Kind::kRightCurly));
+ return Done;
+
+ case Token::Kind::kNumericLiteral: // Ordinal
+ TOKEN_ATTR_CASES:
+ // intentional fallthrough for attribute parsing
+ TOKEN_TYPE_CASES:
+ members.emplace_back(ParseXUnionMember());
+ return More;
+ }
+ };
+
+ while (parse_member() == More) {
+ if (!Ok())
+ Fail();
+
+ ConsumeToken(OfKind(Token::Kind::kSemicolon));
+ if (!Ok())
+ return Fail();
+ }
+
+ if (!Ok())
+ Fail();
+
+ return std::make_unique<raw::XUnionDeclaration>(scope.GetSourceElement(),
+ std::move(attributes), std::move(identifier),
+ std::move(members));
+}
+
std::unique_ptr<raw::File> Parser::ParseFile() {
ASTScope scope(this);
std::vector<std::unique_ptr<raw::Using>> using_list;
@@ -1023,6 +1092,7 @@
std::vector<std::unique_ptr<raw::StructDeclaration>> struct_declaration_list;
std::vector<std::unique_ptr<raw::TableDeclaration>> table_declaration_list;
std::vector<std::unique_ptr<raw::UnionDeclaration>> union_declaration_list;
+ std::vector<std::unique_ptr<raw::XUnionDeclaration>> xunion_declaration_list;
auto attributes = MaybeParseAttributeList();
if (!Ok())
@@ -1058,7 +1128,7 @@
auto parse_declaration = [&const_declaration_list, &enum_declaration_list,
&interface_declaration_list, &struct_declaration_list,
- &table_declaration_list, &union_declaration_list, this]() {
+ &table_declaration_list, &union_declaration_list, &xunion_declaration_list, this]() {
ASTScope scope(this);
std::unique_ptr<raw::AttributeList> attributes = MaybeParseAttributeList();
if (!Ok())
@@ -1092,6 +1162,10 @@
case CASE_IDENTIFIER(Token::Subkind::kUnion):
union_declaration_list.emplace_back(ParseUnionDeclaration(std::move(attributes), scope));
return More;
+
+ case CASE_IDENTIFIER(Token::Subkind::kXUnion):
+ xunion_declaration_list.emplace_back(ParseXUnionDeclaration(std::move(attributes), scope));
+ return More;
}
};
@@ -1111,7 +1185,7 @@
scope.GetSourceElement(), end,
std::move(attributes), std::move(library_name), std::move(using_list), std::move(const_declaration_list),
std::move(enum_declaration_list), std::move(interface_declaration_list),
- std::move(struct_declaration_list), std::move(table_declaration_list), std::move(union_declaration_list));
+ std::move(struct_declaration_list), std::move(table_declaration_list), std::move(union_declaration_list), std::move(xunion_declaration_list));
}
} // namespace fidl
diff --git a/system/host/fidl/lib/raw_ast.cpp b/system/host/fidl/lib/raw_ast.cpp
index a87364f..2a4c494 100644
--- a/system/host/fidl/lib/raw_ast.cpp
+++ b/system/host/fidl/lib/raw_ast.cpp
@@ -24,8 +24,8 @@
void CompoundIdentifier::Accept(TreeVisitor& visitor) {
SourceElementMark sem(visitor, *this);
- for (auto i = components.begin(); i != components.end(); ++i) {
- visitor.OnIdentifier(*i);
+ for (auto& i : components) {
+ visitor.OnIdentifier(i);
}
}
@@ -65,8 +65,8 @@
void AttributeList::Accept(TreeVisitor& visitor) {
SourceElementMark sem(visitor, *this);
- for (auto i = attributes.begin(); i != attributes.end(); ++i) {
- visitor.OnAttribute(*i);
+ for (auto& i : attributes) {
+ visitor.OnAttribute(i);
}
}
@@ -281,43 +281,53 @@
}
}
+void XUnionMember::Accept(TreeVisitor& visitor) {
+ SourceElementMark sem(visitor, *this);
+ if (attributes != nullptr) {
+ visitor.OnAttributeList(attributes);
+ }
+
+ visitor.OnType(type);
+ visitor.OnIdentifier(identifier);
+}
+
+void XUnionDeclaration::Accept(TreeVisitor& visitor) {
+ SourceElementMark sem(visitor, *this);
+ if (attributes != nullptr) {
+ visitor.OnAttributeList(attributes);
+ }
+ visitor.OnIdentifier(identifier);
+ for (auto& member : members) {
+ visitor.OnXUnionMember(member);
+ }
+}
+
void File::Accept(TreeVisitor& visitor) {
SourceElementMark sem(visitor, *this);
visitor.OnCompoundIdentifier(library_name);
- for (auto i = using_list.begin();
- i != using_list.end();
- ++i) {
- visitor.OnUsing(*i);
+ for (auto& i : using_list) {
+ visitor.OnUsing(i);
}
- for (auto i = const_declaration_list.begin();
- i != const_declaration_list.end();
- ++i) {
- visitor.OnConstDeclaration(*i);
+ for (auto& i : const_declaration_list) {
+ visitor.OnConstDeclaration(i);
}
- for (auto i = enum_declaration_list.begin();
- i != enum_declaration_list.end();
- ++i) {
- visitor.OnEnumDeclaration(*i);
+ for (auto& i : enum_declaration_list) {
+ visitor.OnEnumDeclaration(i);
}
- for (auto i = interface_declaration_list.begin();
- i != interface_declaration_list.end();
- ++i) {
- visitor.OnInterfaceDeclaration(*i);
+ for (auto& i : interface_declaration_list) {
+ visitor.OnInterfaceDeclaration(i);
}
- for (auto i = struct_declaration_list.begin();
- i != struct_declaration_list.end();
- ++i) {
- visitor.OnStructDeclaration(*i);
+ for (auto& i : struct_declaration_list) {
+ visitor.OnStructDeclaration(i);
}
- for (auto i = table_declaration_list.begin();
- i != table_declaration_list.end();
- ++i) {
- visitor.OnTableDeclaration(*i);
+ for (auto& i : table_declaration_list) {
+ visitor.OnTableDeclaration(i);
}
- for (auto i = union_declaration_list.begin();
- i != union_declaration_list.end();
- ++i) {
- visitor.OnUnionDeclaration(*i);
+ for (auto& i : union_declaration_list) {
+ visitor.OnUnionDeclaration(i);
+ }
+ for (auto& i : xunion_declaration_list) {
+ visitor.OnXUnionDeclaration(i);
}
}
diff --git a/system/host/fidl/lib/tables_generator.cpp b/system/host/fidl/lib/tables_generator.cpp
index 16c90a9..9bed931 100644
--- a/system/host/fidl/lib/tables_generator.cpp
+++ b/system/host/fidl/lib/tables_generator.cpp
@@ -98,7 +98,7 @@
}
void TablesGenerator::Generate(const coded::StructType& struct_type) {
- Emit(&tables_file_, "static const ::fidl::FidlField ");
+ Emit(&tables_file_, "static const ::fidl::FidlStructField ");
Emit(&tables_file_, NameFields(struct_type.coded_name));
Emit(&tables_file_, "[] = ");
GenerateArray(struct_type.fields);
@@ -157,12 +157,30 @@
Emit(&tables_file_, "\"));\n\n");
}
+void TablesGenerator::Generate(const coded::XUnionType& xunion_type) {
+ Emit(&tables_file_, "static const ::fidl::FidlXUnionField ");
+ Emit(&tables_file_, NameFields(xunion_type.coded_name));
+ Emit(&tables_file_, "[] = ");
+ GenerateArray(xunion_type.fields);
+ Emit(&tables_file_, ";\n");
+
+ Emit(&tables_file_, "const fidl_type_t ");
+ Emit(&tables_file_, NameTable(xunion_type.coded_name));
+ Emit(&tables_file_, " = fidl_type_t(::fidl::FidlCodedXUnion(");
+ Emit(&tables_file_, static_cast<uint32_t>(xunion_type.fields.size()));
+ Emit(&tables_file_, ", ");
+ Emit(&tables_file_, NameFields(xunion_type.coded_name));
+ Emit(&tables_file_, ", \"");
+ Emit(&tables_file_, xunion_type.qname);
+ Emit(&tables_file_, "\"));\n\n");
+}
+
void TablesGenerator::Generate(const coded::MessageType& message_type) {
Emit(&tables_file_, "extern const fidl_type_t ");
Emit(&tables_file_, NameTable(message_type.coded_name));
Emit(&tables_file_, ";\n");
- Emit(&tables_file_, "static const ::fidl::FidlField ");
+ Emit(&tables_file_, "static const ::fidl::FidlStructField ");
Emit(&tables_file_, NameFields(message_type.coded_name));
Emit(&tables_file_, "[] = ");
GenerateArray(message_type.fields);
@@ -262,7 +280,7 @@
}
void TablesGenerator::Generate(const coded::StructField& field) {
- Emit(&tables_file_, "::fidl::FidlField(&");
+ Emit(&tables_file_, "::fidl::FidlStructField(&");
Emit(&tables_file_, NameTable(field.type->coded_name));
Emit(&tables_file_, ", ");
Emit(&tables_file_, field.offset);
@@ -277,6 +295,14 @@
Emit(&tables_file_, ")");
}
+void TablesGenerator::Generate(const coded::XUnionField& field) {
+ Emit(&tables_file_, "::fidl::FidlXUnionField(&");
+ Emit(&tables_file_, NameTable(field.type->coded_name));
+ Emit(&tables_file_, ",");
+ Emit(&tables_file_, field.ordinal);
+ Emit(&tables_file_, ")");
+}
+
void TablesGenerator::GeneratePointerIfNeeded(const coded::StructType& struct_type) {
if (struct_type.referenced_by_pointer) {
Emit(&tables_file_, "static const fidl_type_t ");
@@ -307,6 +333,16 @@
}
}
+void TablesGenerator::GeneratePointerIfNeeded(const coded::XUnionType& xunion_type) {
+ if (xunion_type.referenced_by_pointer) {
+ Emit(&tables_file_, "static const fidl_type_t ");
+ Emit(&tables_file_, NameTable(xunion_type.pointer_name));
+ Emit(&tables_file_, " = fidl_type_t(::fidl::FidlCodedXUnionPointer(&");
+ Emit(&tables_file_, NameTable(xunion_type.coded_name));
+ Emit(&tables_file_, ".coded_xunion));\n");
+ }
+}
+
void TablesGenerator::GenerateForward(const coded::StructType& struct_type) {
Emit(&tables_file_, "extern const fidl_type_t ");
Emit(&tables_file_, NameTable(struct_type.coded_name));
@@ -325,6 +361,12 @@
Emit(&tables_file_, ";\n");
}
+void TablesGenerator::GenerateForward(const coded::XUnionType& xunion_type) {
+ Emit(&tables_file_, "extern const fidl_type_t ");
+ Emit(&tables_file_, NameTable(xunion_type.coded_name));
+ Emit(&tables_file_, ";\n");
+}
+
const coded::Type* TablesGenerator::CompileType(const flat::Type* type) {
switch (type->kind) {
case flat::Type::Kind::kArray: {
@@ -416,7 +458,7 @@
if (iter == named_coded_types_.end()) {
assert(false && "unknown type in named type map!");
}
- // We may need to set the emit-pointer bit on structs and unions now.
+ // We may need to set the emit-pointer bit on structs, unions, and xunions now.
auto coded_type = iter->second.get();
switch (coded_type->kind) {
case coded::Type::Kind::kStruct: {
@@ -452,6 +494,17 @@
coded_union_type->pointer_name, coded_union_type));
return coded_types_.back().get();
}
+ case coded::Type::Kind::kXUnion: {
+ // XUnions were compiled as part of decl compilation,
+ // but we may now need to generate the XUnionPointer.
+ if (identifier_type->nullability != types::Nullability::kNullable)
+ break;
+ auto coded_xunion_type = static_cast<coded::XUnionType*>(coded_type);
+ coded_xunion_type->referenced_by_pointer = true;
+ coded_types_.push_back(std::make_unique<coded::XUnionPointerType>(
+ coded_xunion_type->pointer_name, coded_xunion_type));
+ return coded_types_.back().get();
+ }
case coded::Type::Kind::kInterface: {
auto iter = interface_type_map_.find(identifier_type);
if (iter != interface_type_map_.end())
@@ -471,6 +524,7 @@
case coded::Type::Kind::kStructPointer:
case coded::Type::Kind::kTablePointer:
case coded::Type::Kind::kUnionPointer:
+ case coded::Type::Kind::kXUnionPointer:
case coded::Type::Kind::kMessage:
case coded::Type::Kind::kRequestHandle:
case coded::Type::Kind::kHandle:
@@ -555,6 +609,27 @@
}
break;
}
+ case flat::Decl::Kind::kXUnion: {
+ auto xunion_decl = static_cast<const flat::XUnion*>(decl);
+ auto coded_xunion =
+ static_cast<coded::XUnionType*>(named_coded_types_[&decl->name].get());
+
+ std::map<uint32_t, const flat::XUnion::Member*> members;
+ for (const auto& member : xunion_decl->members) {
+ if (!members.emplace(member.ordinal->value, &member).second) {
+ assert(false && "Duplicate ordinal found in table generation");
+ }
+ }
+
+ for (const auto& member_pair : members) {
+ const auto& member = *member_pair.second;
+ auto coded_member_type = CompileType(member.type.get());
+ if (coded_member_type->coding_needed == coded::CodingNeeded::kNeeded) {
+ coded_xunion->fields.emplace_back(coded_member_type, member.ordinal->value);
+ }
+ }
+ break;
+ }
case flat::Decl::Kind::kTable: {
auto table_decl = static_cast<const flat::Table*>(decl);
coded::TableType* coded_table =
@@ -578,7 +653,9 @@
}
break;
}
- default: { break; }
+ default: {
+ break;
+ }
}
}
@@ -662,6 +739,16 @@
std::move(pointer_name), NameName(union_decl->name, ".", "/")));
break;
}
+ case flat::Decl::Kind::kXUnion: {
+ auto xunion_decl = static_cast<const flat::XUnion*>(decl);
+ std::string xunion_name = NameCodedXUnion(xunion_decl);
+ std::string pointer_name = NamePointer(xunion_name);
+ named_coded_types_.emplace(
+ &decl->name, std::make_unique<coded::XUnionType>(
+ std::move(xunion_name), std::vector<coded::XUnionField>(),
+ std::move(pointer_name), NameName(xunion_decl->name, ".", "/")));
+ break;
+ }
}
}
@@ -692,6 +779,9 @@
case coded::Type::Kind::kUnion:
GenerateForward(*static_cast<const coded::UnionType*>(coded_type));
break;
+ case coded::Type::Kind::kXUnion:
+ GenerateForward(*static_cast<const coded::XUnionType*>(coded_type));
+ break;
default:
break;
}
@@ -713,6 +803,9 @@
case coded::Type::Kind::kUnion:
GeneratePointerIfNeeded(*static_cast<const coded::UnionType*>(coded_type));
break;
+ case coded::Type::Kind::kXUnion:
+ GeneratePointerIfNeeded(*static_cast<const coded::XUnionType*>(coded_type));
+ break;
default:
break;
}
@@ -731,6 +824,8 @@
case coded::Type::Kind::kTablePointer:
case coded::Type::Kind::kUnion:
case coded::Type::Kind::kUnionPointer:
+ case coded::Type::Kind::kXUnion:
+ case coded::Type::Kind::kXUnionPointer:
// These are generated in the next phase.
break;
case coded::Type::Kind::kInterface:
@@ -784,6 +879,9 @@
case coded::Type::Kind::kUnion:
Generate(*static_cast<const coded::UnionType*>(coded_type));
break;
+ case coded::Type::Kind::kXUnion:
+ Generate(*static_cast<const coded::XUnionType*>(coded_type));
+ break;
default:
continue;
}
diff --git a/system/host/fidl/lib/tree_visitor.cpp b/system/host/fidl/lib/tree_visitor.cpp
index e7eecd0..44020ba 100644
--- a/system/host/fidl/lib/tree_visitor.cpp
+++ b/system/host/fidl/lib/tree_visitor.cpp
@@ -26,6 +26,7 @@
auto struct_decls_it = element->struct_declaration_list.begin();
auto table_decls_it = element->table_declaration_list.begin();
auto union_decls_it = element->union_declaration_list.begin();
+ auto xunion_decls_it = element->xunion_declaration_list.begin();
enum Next {
const_t,
@@ -33,7 +34,8 @@
interface_t,
struct_t,
table_t,
- union_t
+ union_t,
+ xunion_t,
};
std::map<const char*, Next> m;
@@ -69,6 +71,9 @@
if (union_decls_it != element->union_declaration_list.end()) {
m[(*union_decls_it)->start_.previous_end().data().data()] = union_t;
}
+ if (xunion_decls_it != element->xunion_declaration_list.end()) {
+ m[(*xunion_decls_it)->start_.previous_end().data().data()] = xunion_t;
+ }
if (m.size() == 0)
break;
@@ -98,6 +103,10 @@
OnUnionDeclaration(*union_decls_it);
++union_decls_it;
break;
+ case xunion_t:
+ OnXUnionDeclaration(*xunion_decls_it);
+ ++xunion_decls_it;
+ break;
}
} while (1);
OnSourceElementEnd(*element);
diff --git a/system/host/fidl/schema.json b/system/host/fidl/schema.json
index 0ccae74..cc6bf3b 100644
--- a/system/host/fidl/schema.json
+++ b/system/host/fidl/schema.json
@@ -11,6 +11,7 @@
"struct_declarations",
"table_declarations",
"union_declarations",
+ "xunion_declarations",
"declaration_order",
"declarations",
"library_dependencies"
@@ -66,6 +67,13 @@
"$ref": "#/definitions/union"
}
},
+ "xunion_declarations": {
+ "description": "List of extensible unions",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/xunion"
+ }
+ },
"declaration_order": {
"description": "List of declarations in declaration order",
"type": "array",
@@ -555,6 +563,97 @@
}
}
},
+ "xunion": {
+ "description": "Definition of an extensible union",
+ "type": "object",
+ "required": [
+ "name",
+ "members",
+ "size",
+ "max_out_of_line",
+ "alignment"
+ ],
+ "properties": {
+ "max_handles": {
+ "description": "Maximum number of handles present in the extensible union",
+ "$ref": "#/definitions/count"
+ },
+ "maybe_attributes": {
+ "description": "Optional list of extensible union attributes",
+ "$ref": "#/definitions/attributes-list"
+ },
+ "name": {
+ "description": "Name of extensible union",
+ "$ref": "#/definitions/compound-identifier"
+ },
+ "members": {
+ "description": "List of extensible union members",
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/xunion-member"
+ }
+ },
+ "size": {
+ "description": "Size of extensible union",
+ "$ref": "#/definitions/count"
+ },
+ "max_out_of_line": {
+ "description": "Maximum size of the out-of-line payload",
+ "$ref": "#/definitions/count"
+ },
+ "alignment": {
+ "description": "Alignment of extensible union",
+ "$ref": "#/definitions/count"
+ }
+ }
+ },
+ "xunion-member": {
+ "description": "Definition of an extensible union member",
+ "type": "object",
+ "required": [
+ "ordinal",
+ "type",
+ "name",
+ "size",
+ "max_out_of_line",
+ "alignment",
+ "offset"
+ ],
+ "properties": {
+ "ordinal": {
+ "description": "Ordinal value of extensible union member",
+ "$ref": "#/definitions/ordinal"
+ },
+ "type": {
+ "description": "Type of extensible union member",
+ "$ref": "#/definitions/type"
+ },
+ "name": {
+ "description": "Name of extensible union member",
+ "$ref": "#/definitions/identifier"
+ },
+ "size": {
+ "description": "Size of extensible union member",
+ "$ref": "#/definitions/count"
+ },
+ "max_out_of_line": {
+ "description": "Maximum size of the out-of-line payload",
+ "$ref": "#/definitions/count"
+ },
+ "alignment": {
+ "description": "Alignment of extensible union member",
+ "$ref": "#/definitions/count"
+ },
+ "offset": {
+ "description": "Offset of extensible union member",
+ "$ref": "#/definitions/count"
+ },
+ "maybe_attributes": {
+ "description": "Optional list of extensible union member attributes",
+ "$ref": "#/definitions/attributes-list"
+ }
+ }
+ },
"declarations-map": {
"description": "Definition of declarations of a library",
"type": "object",
@@ -567,7 +666,8 @@
"interface",
"struct",
"table",
- "union"
+ "union",
+ "xunion"
]
}
}
diff --git a/system/public/zircon/fidl.h b/system/public/zircon/fidl.h
index 5209ea5..e863a96 100644
--- a/system/public/zircon/fidl.h
+++ b/system/public/zircon/fidl.h
@@ -5,9 +5,9 @@
#ifndef ZIRCON_FIDL_H_
#define ZIRCON_FIDL_H_
-#include <assert.h>
-#include <stdalign.h>
-#include <stdint.h>
+#include <assert.h> // NOLINT(modernize-deprecated-headers, foobar)
+#include <stdalign.h> // NOLINT(modernize-deprecated-headers)
+#include <stdint.h> // NOLINT(modernize-*)
#include <zircon/compiler.h>
#include <zircon/types.h>
@@ -15,7 +15,7 @@
__BEGIN_CDECLS
// Fidl data types have a representation in a wire format. This wire
-// format is shared by all language bindings, including C11 and C++14.
+// format is shared by all language bindings, including C11 and C++.
//
// The C bindings also define a representation of fidl data types. For
// a given type, the size and alignment of all parts of the type agree
@@ -199,7 +199,8 @@
// - Stores a variable size uninterpreted payload out-of-line.
// - Payload may contain an arbitrary number of bytes and handles.
// - Allows for encapsulation of one FIDL message inside of another.
-// - Building block for derived structures such as Tables.
+// - Building block for extensible structures such as tables & extensible
+// unions.
// When encoded for transfer, |data| indicates presence of content:
// - FIDL_ALLOC_ABSENT : envelope is null
@@ -208,16 +209,24 @@
// - nullptr : envelope is null
// - <valid pointer> : envelope is non-null, |data| is at indicated memory address
-typedef struct fidl_envelope {
- // Number of bytes in the envelope.
- // Always a multiple of 8; must be zero if envelope is null.
+typedef struct {
+ // The size of the entire envelope contents, including any additional
+ // out-of-line objects that the envelope may contain. For example, a
+ // vector<string>'s num_bytes for ["hello", "world"] would include the
+ // string contents in the size, not just the outer vector. Always a multiple
+ // of 8; must be zero if envelope is null.
uint32_t num_bytes;
- // Number of handles in envelope; must be zero if envelope is null.
+ // The number of handles in the envelope, including any additional
+ // out-of-line objects that the envelope contains. Must be zero if envelope is null.
uint32_t num_handles;
- // Pointer to out-of-line data.
- void* data;
+ // A pointer to the out-of-line envelope data in decoded form, or
+ // FIDL_ALLOC_(ABSENT|PRESENT) in encoded form.
+ union {
+ void* data;
+ uintptr_t presence;
+ };
} fidl_envelope_t;
// Handle types.
@@ -305,6 +314,22 @@
// union_foo, or else
// FIDL_ALLOC_ABSENT.
+// Extensible unions.
+
+// Extensible unions, or "xunions" (colloquially pronounced "zoo-nions") are
+// similar to unions, except that storage for union members are out-of-line
+// rather than inline. This enables union members to be added and removed while
+// preserving ABI compatibility with the existing xunion definition. Like
+// unions, xunions have a 4-byte tag, and may be nullable.
+
+typedef uint32_t fidl_xunion_tag_t;
+
+typedef struct {
+ fidl_xunion_tag_t tag;
+ uint32_t padding; // Should always be zero.
+ fidl_envelope_t envelope;
+} fidl_xunion_t;
+
// Messages.
// All fidl messages share a common 16 byte header.
diff --git a/system/ulib/fidl/buffer_walker.h b/system/ulib/fidl/buffer_walker.h
index 0f85ece..93d9484 100644
--- a/system/ulib/fidl/buffer_walker.h
+++ b/system/ulib/fidl/buffer_walker.h
@@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#pragma once
+#ifndef ZIRCON_SYSTEM_ULIB_FIDL_BUFFER_WALKER_H_
+#define ZIRCON_SYSTEM_ULIB_FIDL_BUFFER_WALKER_H_
+
+#include <lib/fidl/internal.h>
+#include <cstdlib>
#include <cstdint>
#include <cstdlib>
@@ -125,7 +129,7 @@
Pop();
continue;
}
- const fidl::FidlField& field = frame->struct_state.fields[field_index];
+ const fidl::FidlStructField& field = frame->struct_state.fields[field_index];
const fidl_type_t* field_type = field.type;
const uint32_t field_offset = frame->offset + field.offset;
if (!Push(Frame(field_type, field_offset))) {
@@ -235,12 +239,12 @@
const uint32_t table_bytes = static_cast<uint32_t>(packed_sizes & 0xffffffffu);
const uint32_t table_handles = static_cast<uint32_t>(packed_sizes >> 32);
if (add_overflow(out_of_line_offset_, table_bytes, &offset) || offset > num_bytes()) {
- SetError("integer overflow decoding table field");
+ SetError("table is larger than expected");
FIDL_POP_AND_CONTINUE_OR_RETURN;
}
if (add_overflow(handle_idx_, table_handles, &handles) ||
handles > num_handles()) {
- SetError("integer overflow decoding table handles");
+ SetError("table has more handles than expected");
FIDL_POP_AND_CONTINUE_OR_RETURN;
}
frame->table_state.end_offset = offset;
@@ -295,6 +299,125 @@
*frame = Frame(coded_table, frame->offset);
continue;
}
+ case Frame::kStateXUnion: {
+ auto xunion = TypedAt<fidl_xunion_t>(frame->offset);
+
+ if (xunion->padding != 0) {
+ SetError("xunion padding after discriminant are non-zero");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+
+ uint32_t end_offset;
+ if (add_overflow(out_of_line_offset_, xunion->envelope.num_bytes, &end_offset) || end_offset > num_bytes()) {
+ SetError("xunion size is larger than expected");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+
+ uint32_t total_handle_count;
+ if (add_overflow(handle_idx_, xunion->envelope.num_handles, &total_handle_count) ||
+ total_handle_count > num_handles()) {
+ SetError("xunion has more handles than expected");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+
+ switch (GetPointerState(&xunion->envelope.data)) {
+ case PointerState::PRESENT:
+ if (xunion->tag == 0) {
+ SetError("xunion has zero discriminant but envelope is present");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+ break;
+ case PointerState::ABSENT:
+ if (xunion->tag != 0) {
+ SetError("xunion has non-zero discriminant but no data");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+
+ // Empty xunion.
+ frame->offset += static_cast<uint32_t>(sizeof(fidl_xunion_t));
+ Pop();
+ continue;
+ case PointerState::INVALID:
+ default:
+ SetError("xunion has invalid envelope pointer");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ break;
+ }
+
+ const FidlXUnionField* known_field = nullptr;
+ for (size_t i = 0; i < frame->xunion_state.field_count; i++) {
+ const auto field = frame->xunion_state.fields + i;
+
+ if (field->ordinal == xunion->tag) {
+ known_field = field;
+ break;
+ }
+ }
+
+ auto claim_data = [&](uint32_t known_size, uint32_t* envelope_offset) {
+ if (!ClaimOutOfLineStorage(known_size, xunion->envelope.data, envelope_offset)) {
+ SetError("xunion out-of-line storage claim couldn't be validated");
+ return false;
+ }
+
+ if (*envelope_offset + xunion->envelope.num_bytes != end_offset) {
+ SetError("expected xunion end offset doesn't match envelope offset + recursive size");
+ return false;
+ }
+
+ UpdatePointer(&xunion->envelope.data, TypedAt<void>(*envelope_offset));
+
+ return true;
+ };
+
+ uint32_t envelope_offset;
+ if (known_field != nullptr) {
+ if (!claim_data(TypeSize(known_field->type), &envelope_offset)) {
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+
+ frame->offset = envelope_offset;
+ *frame = Frame(known_field->type, envelope_offset);
+ } else {
+ if (!claim_data(xunion->envelope.num_bytes, &envelope_offset)) {
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+
+ for (uint32_t i = 0; i < xunion->envelope.num_handles; i++) {
+ if (!ClaimHandle(nullptr)) {
+ SetError("expected handle not present");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+ }
+
+ frame->offset = end_offset;
+ Pop();
+ }
+
+ continue;
+ }
+ case Frame::kStateXUnionPointer: {
+ auto xunion_ptr_ptr = TypedAt<fidl_xunion_tag_t*>(frame->offset);
+ switch (GetPointerState(TypedAt<void>(frame->offset))) {
+ case PointerState::PRESENT:
+ break;
+ case PointerState::ABSENT:
+ Pop();
+ continue;
+ default:
+ SetError("Tried to decode a bad xunion pointer");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+ if (!ClaimOutOfLineStorage(sizeof(fidl_xunion_t), *xunion_ptr_ptr,
+ &frame->offset)) {
+ SetError("message wanted to store too large of a nullable xunion");
+ FIDL_POP_AND_CONTINUE_OR_RETURN;
+ }
+ UpdatePointer(xunion_ptr_ptr, TypedAt<fidl_xunion_tag_t>(frame->offset));
+ const fidl::FidlCodedXUnion* coded_xunion = frame->xunion_pointer_state.xunion_type;
+ *frame = Frame(coded_xunion, frame->offset);
+ continue;
+ }
case Frame::kStateUnion: {
fidl_union_tag_t union_tag = *TypedAt<fidl_union_tag_t>(frame->offset);
if (union_tag >= frame->union_state.type_count) {
@@ -403,11 +526,13 @@
}
Pop();
continue;
- default:
+ case HandleState::INVALID:
+ default: {
// The value at the handle was garbage.
SetError("message tried to decode a garbage handle");
FIDL_POP_AND_CONTINUE_OR_RETURN;
}
+ }
}
case Frame::kStateVector: {
auto vector_ptr = TypedAt<fidl_vector_t>(frame->offset);
@@ -578,6 +703,7 @@
case fidl::kFidlTypeStructPointer:
case fidl::kFidlTypeTablePointer:
case fidl::kFidlTypeUnionPointer:
+ case fidl::kFidlTypeXUnionPointer:
return sizeof(uint64_t);
case fidl::kFidlTypeHandle:
return sizeof(zx_handle_t);
@@ -587,6 +713,8 @@
return sizeof(fidl_vector_t);
case fidl::kFidlTypeUnion:
return type->coded_union.size;
+ case fidl::kFidlTypeXUnion:
+ return sizeof(fidl_xunion_t);
case fidl::kFidlTypeString:
return sizeof(fidl_string_t);
case fidl::kFidlTypeArray:
@@ -632,6 +760,15 @@
state = kStateUnionPointer;
union_pointer_state.union_type = fidl_type->coded_union_pointer.union_type;
break;
+ case fidl::kFidlTypeXUnion:
+ state = kStateXUnion;
+ xunion_state.fields = fidl_type->coded_xunion.fields;
+ xunion_state.field_count = fidl_type->coded_xunion.field_count;
+ break;
+ case fidl::kFidlTypeXUnionPointer:
+ state = kStateXUnionPointer;
+ xunion_pointer_state.xunion_type = fidl_type->coded_xunion_pointer.xunion_type;
+ break;
case fidl::kFidlTypeArray:
state = kStateArray;
array_state.element = fidl_type->coded_array.element;
@@ -679,6 +816,15 @@
union_state.data_offset = coded_union->data_offset;
}
+ Frame(const fidl::FidlCodedXUnion* coded_xunion, uint32_t offset)
+ : state(kStateXUnion), offset(offset) {
+ // This initialization is done in the ctor body instead of in an
+ // initialization list since we need to set fields in unions, which
+ // is much more involved in a ctor initialization list.
+ xunion_state.fields = coded_xunion->fields;
+ xunion_state.field_count = coded_xunion->field_count;
+ }
+
Frame(const fidl_type_t* element, uint32_t array_size, uint32_t element_size,
uint32_t offset)
: offset(offset) {
@@ -724,6 +870,8 @@
kStateString,
kStateHandle,
kStateVector,
+ kStateXUnion,
+ kStateXUnionPointer,
kStateDone,
} state;
@@ -735,7 +883,7 @@
// example, struct sizes do not need to be present here.
union {
struct {
- const fidl::FidlField* fields;
+ const fidl::FidlStructField* fields;
uint32_t field_count;
} struct_state;
struct {
@@ -761,6 +909,13 @@
const fidl::FidlCodedUnion* union_type;
} union_pointer_state;
struct {
+ const fidl::FidlXUnionField* fields;
+ uint32_t field_count;
+ } xunion_state;
+ struct {
+ const fidl::FidlCodedXUnion* xunion_type;
+ } xunion_pointer_state;
+ struct {
const fidl_type_t* element;
uint32_t array_size;
uint32_t element_size;
@@ -817,3 +972,5 @@
} // namespace internal
} // namespace fidl
+
+#endif // ZIRCON_SYSTEM_ULIB_FIDL_BUFFER_WALKER_H_
diff --git a/system/ulib/fidl/include/lib/fidl/internal.h b/system/ulib/fidl/include/lib/fidl/internal.h
index efef16e..b814fd9 100644
--- a/system/ulib/fidl/include/lib/fidl/internal.h
+++ b/system/ulib/fidl/include/lib/fidl/internal.h
@@ -35,14 +35,18 @@
return (offset + alignment_mask) & ~alignment_mask;
}
-struct FidlField {
+struct FidlStructField {
const fidl_type* type;
uint32_t offset;
- constexpr FidlField(const fidl_type* type, uint32_t offset)
+ constexpr FidlStructField(const fidl_type* type, uint32_t offset)
: type(type), offset(offset) {}
};
+// TODO(apang): Remove this backward-compatible typedef after all dependencies
+// have been updated from FidlField to FidlStructField.
+using FidlField = FidlStructField;
+
struct FidlTableField {
const fidl_type* type;
uint32_t ordinal;
@@ -51,28 +55,38 @@
: type(type), ordinal(ordinal) {}
};
+struct FidlXUnionField {
+ const fidl_type* type;
+ uint32_t ordinal;
+
+ constexpr FidlXUnionField(const fidl_type* type, uint32_t ordinal)
+ : type(type), ordinal(ordinal) {}
+};
+
enum FidlTypeTag : uint32_t {
- kFidlTypeStruct = 0u,
- kFidlTypeStructPointer = 1u,
- kFidlTypeTable = 8u,
- kFidlTypeTablePointer = 9u,
- kFidlTypeUnion = 2u,
- kFidlTypeUnionPointer = 3u,
- kFidlTypeArray = 4u,
- kFidlTypeString = 5u,
- kFidlTypeHandle = 6u,
- kFidlTypeVector = 7u,
+ kFidlTypeStruct,
+ kFidlTypeStructPointer,
+ kFidlTypeUnion,
+ kFidlTypeUnionPointer,
+ kFidlTypeArray,
+ kFidlTypeString,
+ kFidlTypeHandle,
+ kFidlTypeVector,
+ kFidlTypeTable,
+ kFidlTypeTablePointer,
+ kFidlTypeXUnion,
+ kFidlTypeXUnionPointer,
};
// Though the |size| is implied by the fields, computing that information is not the purview of this
// library. It's easier for the compiler to stash it.
struct FidlCodedStruct {
- const FidlField* const fields;
+ const FidlStructField* const fields;
const uint32_t field_count;
const uint32_t size;
const char* name; // may be nullptr if omitted at compile time
- constexpr FidlCodedStruct(const FidlField* fields, uint32_t field_count, uint32_t size,
+ constexpr FidlCodedStruct(const FidlStructField* fields, uint32_t field_count, uint32_t size,
const char* name)
: fields(fields), field_count(field_count), size(size), name(name) {}
};
@@ -101,8 +115,8 @@
: table_type(table_type) {}
};
-// Unlike structs, union members do not have different offsets, so this points to an array of
-// |fidl_type*| rather than |FidlField|.
+// Unlike structs, union members do not have different offsets, so this points
+// to an array of |fidl_type*| rather than |FidlStructField|.
//
// On-the-wire unions begin with a tag which is an index into |types|.
// |data_offset| is the offset of the data in the wire format (tag + padding).
@@ -125,6 +139,22 @@
: union_type(union_type) {}
};
+struct FidlCodedXUnion {
+ const uint32_t field_count;
+ const FidlXUnionField* const fields;
+ const char* name; // may be nullptr if omitted at compile time
+
+ constexpr FidlCodedXUnion(uint32_t field_count, const FidlXUnionField* fields, const char* name)
+ : field_count(field_count), fields(fields), name(name) {}
+};
+
+struct FidlCodedXUnionPointer {
+ const FidlCodedXUnion* const xunion_type;
+
+ constexpr explicit FidlCodedXUnionPointer(const FidlCodedXUnion* xunion_type)
+ : xunion_type(xunion_type) {}
+};
+
// An array is essentially a struct with |array_size / element_size| of the same field, named at
// |element|.
struct FidlCodedArray {
@@ -202,6 +232,8 @@
const fidl::FidlCodedTablePointer coded_table_pointer;
const fidl::FidlCodedUnion coded_union;
const fidl::FidlCodedUnionPointer coded_union_pointer;
+ const fidl::FidlCodedXUnion coded_xunion;
+ const fidl::FidlCodedXUnionPointer coded_xunion_pointer;
const fidl::FidlCodedHandle coded_handle;
const fidl::FidlCodedString coded_string;
const fidl::FidlCodedArray coded_array;
@@ -226,6 +258,12 @@
constexpr fidl_type(fidl::FidlCodedUnionPointer coded_union_pointer)
: type_tag(fidl::kFidlTypeUnionPointer), coded_union_pointer(coded_union_pointer) {}
+ constexpr fidl_type(fidl::FidlCodedXUnion coded_xunion)
+ : type_tag(fidl::kFidlTypeXUnion), coded_xunion(coded_xunion) {}
+
+ constexpr fidl_type(fidl::FidlCodedXUnionPointer coded_xunion_pointer)
+ : type_tag(fidl::kFidlTypeXUnionPointer), coded_xunion_pointer(coded_xunion_pointer) {}
+
constexpr fidl_type(fidl::FidlCodedHandle coded_handle)
: type_tag(fidl::kFidlTypeHandle), coded_handle(coded_handle) {}
diff --git a/system/ulib/fidl/walker.h b/system/ulib/fidl/walker.h
index 67658fa..68d2066 100644
--- a/system/ulib/fidl/walker.h
+++ b/system/ulib/fidl/walker.h
@@ -42,6 +42,7 @@
case fidl::kFidlTypeStructPointer:
case fidl::kFidlTypeTablePointer:
case fidl::kFidlTypeUnionPointer:
+ case fidl::kFidlTypeXUnionPointer:
return sizeof(uint64_t);
case fidl::kFidlTypeHandle:
return sizeof(zx_handle_t);
@@ -51,15 +52,16 @@
return sizeof(fidl_vector_t);
case fidl::kFidlTypeUnion:
return type->coded_union.size;
+ case fidl::kFidlTypeXUnion:
+ return sizeof(fidl_xunion_t);
case fidl::kFidlTypeString:
return sizeof(fidl_string_t);
case fidl::kFidlTypeArray:
return type->coded_array.array_size;
case fidl::kFidlTypeVector:
return sizeof(fidl_vector_t);
- default:
- __builtin_unreachable();
}
+ __builtin_unreachable();
}
// The Walker class traverses through a FIDL message by following its encoding table and
@@ -134,6 +136,15 @@
state = kStateUnionPointer;
union_pointer_state.union_type = fidl_type->coded_union_pointer.union_type;
break;
+ case fidl::kFidlTypeXUnion:
+ state = kStateXUnion;
+ xunion_state.fields = fidl_type->coded_xunion.fields;
+ xunion_state.field_count = fidl_type->coded_xunion.field_count;
+ break;
+ case fidl::kFidlTypeXUnionPointer:
+ state = kStateXUnionPointer;
+ xunion_pointer_state.xunion_type = fidl_type->coded_xunion_pointer.xunion_type;
+ break;
case fidl::kFidlTypeArray:
state = kStateArray;
array_state.element = fidl_type->coded_array.element;
@@ -185,6 +196,15 @@
union_state.data_offset = coded_union->data_offset;
}
+ Frame(const fidl::FidlCodedXUnion* coded_xunion, Position position)
+ : state(kStateXUnion), position(position) {
+ // This initialization is done in the ctor body instead of in an
+ // initialization list since we need to set fields in unions, which
+ // is much more involved in a ctor initialization list.
+ xunion_state.fields = coded_xunion->fields;
+ xunion_state.field_count = coded_xunion->field_count;
+ }
+
Frame(const fidl_type_t* element, uint32_t array_size, uint32_t element_size,
Position position)
: position(position) {
@@ -227,6 +247,8 @@
kStateTablePointer,
kStateUnion,
kStateUnionPointer,
+ kStateXUnion,
+ kStateXUnionPointer,
kStateArray,
kStateString,
kStateHandle,
@@ -282,6 +304,13 @@
const fidl::FidlCodedUnion* union_type;
} union_pointer_state;
struct {
+ const fidl::FidlXUnionField* fields;
+ uint32_t field_count;
+ } xunion_state;
+ struct {
+ const fidl::FidlCodedXUnion* xunion_type;
+ } xunion_pointer_state;
+ struct {
const fidl_type_t* element;
// Size of the entire array in bytes
uint32_t array_size;
@@ -527,6 +556,14 @@
*frame = Frame(coded_union, frame->position);
continue;
}
+ case Frame::kStateXUnion: {
+ assert(false && "xunions not implemented yet");
+ continue;
+ }
+ case Frame::kStateXUnionPointer: {
+ assert(false && "xunion pointers not implemented yet");
+ continue;
+ }
case Frame::kStateArray: {
const uint32_t element_offset = frame->NextArrayOffset();
if (element_offset == frame->array_state.array_size) {
diff --git a/system/ulib/trace-provider/trace_provider.fidl.tables.cpp b/system/ulib/trace-provider/trace_provider.fidl.tables.cpp
index d8c2bb8..0bcef6d 100644
--- a/system/ulib/trace-provider/trace_provider.fidl.tables.cpp
+++ b/system/ulib/trace-provider/trace_provider.fidl.tables.cpp
@@ -10,7 +10,7 @@
// --files system/fidl/fuchsia-tracelink/tracelink.fidl
//
// and then this header (up to "End of additions ...") manually inserted.
-//
+//
// There are *no* differences with the machine generated version except the
// addition of this text.
// Minimizing differences with generated code is critical to lessening the
@@ -29,8 +29,6 @@
extern "C" {
-
-
static const fidl_type_t HandlevmononnullableTable = fidl_type_t(::fidl::FidlCodedHandle(ZX_OBJ_TYPE_VMO, ::fidl::kNonnullable));
static const fidl_type_t HandlefifononnullableTable = fidl_type_t(::fidl::FidlCodedHandle(ZX_OBJ_TYPE_FIFO, ::fidl::kNonnullable));
@@ -40,41 +38,37 @@
static const fidl_type_t VectorString100nonnullable100nonnullableTable = fidl_type_t(::fidl::FidlCodedVector(&String100nonnullableTable, 100, 16, ::fidl::kNonnullable));
extern const fidl_type_t fuchsia_tracelink_ProviderStartRequestTable;
-static const ::fidl::FidlField fuchsia_tracelink_ProviderStartRequestFields[] = {
- ::fidl::FidlField(&HandlevmononnullableTable, 20),
- ::fidl::FidlField(&HandlefifononnullableTable, 24),
- ::fidl::FidlField(&VectorString100nonnullable100nonnullableTable, 32)
-};
+static const ::fidl::FidlStructField fuchsia_tracelink_ProviderStartRequestFields[] = {
+ ::fidl::FidlStructField(&HandlevmononnullableTable, 20),
+ ::fidl::FidlStructField(&HandlefifononnullableTable, 24),
+ ::fidl::FidlStructField(&VectorString100nonnullable100nonnullableTable, 32)};
const fidl_type_t fuchsia_tracelink_ProviderStartRequestTable = fidl_type_t(::fidl::FidlCodedStruct(fuchsia_tracelink_ProviderStartRequestFields, 3, 48, "fuchsia.tracelink/ProviderStartRequest"));
extern const fidl_type_t fuchsia_tracelink_ProviderStopRequestTable;
-static const ::fidl::FidlField fuchsia_tracelink_ProviderStopRequestFields[] = {};
+static const ::fidl::FidlStructField fuchsia_tracelink_ProviderStopRequestFields[] = {};
const fidl_type_t fuchsia_tracelink_ProviderStopRequestTable = fidl_type_t(::fidl::FidlCodedStruct(fuchsia_tracelink_ProviderStopRequestFields, 0, 16, "fuchsia.tracelink/ProviderStopRequest"));
static const fidl_type_t fuchsia_tracelink_ProviderInterfacenonnullableTable = fidl_type_t(::fidl::FidlCodedHandle(ZX_OBJ_TYPE_CHANNEL, ::fidl::kNonnullable));
extern const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderDeprecatedRequestTable;
-static const ::fidl::FidlField fuchsia_tracelink_RegistryRegisterTraceProviderDeprecatedRequestFields[] = {
- ::fidl::FidlField(&fuchsia_tracelink_ProviderInterfacenonnullableTable, 16)
-};
+static const ::fidl::FidlStructField fuchsia_tracelink_RegistryRegisterTraceProviderDeprecatedRequestFields[] = {
+ ::fidl::FidlStructField(&fuchsia_tracelink_ProviderInterfacenonnullableTable, 16)};
const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderDeprecatedRequestTable = fidl_type_t(::fidl::FidlCodedStruct(fuchsia_tracelink_RegistryRegisterTraceProviderDeprecatedRequestFields, 1, 20, "fuchsia.tracelink/RegistryRegisterTraceProviderDeprecatedRequest"));
extern const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderRequestTable;
-static const ::fidl::FidlField fuchsia_tracelink_RegistryRegisterTraceProviderRequestFields[] = {
- ::fidl::FidlField(&fuchsia_tracelink_ProviderInterfacenonnullableTable, 16),
- ::fidl::FidlField(&String100nonnullableTable, 32)
-};
+static const ::fidl::FidlStructField fuchsia_tracelink_RegistryRegisterTraceProviderRequestFields[] = {
+ ::fidl::FidlStructField(&fuchsia_tracelink_ProviderInterfacenonnullableTable, 16),
+ ::fidl::FidlStructField(&String100nonnullableTable, 32)};
const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderRequestTable = fidl_type_t(::fidl::FidlCodedStruct(fuchsia_tracelink_RegistryRegisterTraceProviderRequestFields, 2, 48, "fuchsia.tracelink/RegistryRegisterTraceProviderRequest"));
extern const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyRequestTable;
-static const ::fidl::FidlField fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyRequestFields[] = {
- ::fidl::FidlField(&fuchsia_tracelink_ProviderInterfacenonnullableTable, 16),
- ::fidl::FidlField(&String100nonnullableTable, 32)
-};
+static const ::fidl::FidlStructField fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyRequestFields[] = {
+ ::fidl::FidlStructField(&fuchsia_tracelink_ProviderInterfacenonnullableTable, 16),
+ ::fidl::FidlStructField(&String100nonnullableTable, 32)};
const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyRequestTable = fidl_type_t(::fidl::FidlCodedStruct(fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyRequestFields, 2, 48, "fuchsia.tracelink/RegistryRegisterTraceProviderSynchronouslyRequest"));
extern const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyResponseTable;
-static const ::fidl::FidlField fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyResponseFields[] = {};
+static const ::fidl::FidlStructField fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyResponseFields[] = {};
const fidl_type_t fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyResponseTable = fidl_type_t(::fidl::FidlCodedStruct(fuchsia_tracelink_RegistryRegisterTraceProviderSynchronouslyResponseFields, 0, 24, "fuchsia.tracelink/RegistryRegisterTraceProviderSynchronouslyResponse"));
} // extern "C"
diff --git a/system/utest/fidl-compiler/attributes_tests.cpp b/system/utest/fidl-compiler/attributes_tests.cpp
index b2419b6..4b7c748 100644
--- a/system/utest/fidl-compiler/attributes_tests.cpp
+++ b/system/utest/fidl-compiler/attributes_tests.cpp
@@ -368,6 +368,29 @@
END_TEST;
}
+bool selector_incorrect_placement() {
+ BEGIN_TEST;
+
+ TestLibrary library(R"FIDL(
+library fidl.test;
+
+[Selector = "Nonsense"]
+union MyUnion {
+ uint8 hello;
+};
+
+)FIDL");
+ EXPECT_FALSE(library.Compile());
+ auto errors = library.errors();
+ ASSERT_EQ(errors.size(), 1);
+ ASSERT_STR_STR(errors[0].c_str(),
+ "placement of attribute");
+ ASSERT_STR_STR(errors[0].c_str(),
+ "disallowed here");
+
+ END_TEST;
+}
+
} // namespace
BEGIN_TEST_CASE(attributes_tests);
@@ -385,4 +408,5 @@
RUN_TEST(constraint_only_three_members_on_interface);
RUN_TEST(max_bytes);
RUN_TEST(max_handles);
+RUN_TEST(selector_incorrect_placement);
END_TEST_CASE(attributes_tests);
diff --git a/system/utest/fidl-compiler/json_generator_tests.cpp b/system/utest/fidl-compiler/json_generator_tests.cpp
index 2df3f82..6143085 100644
--- a/system/utest/fidl-compiler/json_generator_tests.cpp
+++ b/system/utest/fidl-compiler/json_generator_tests.cpp
@@ -119,6 +119,7 @@
],
"table_declarations": [],
"union_declarations": [],
+ "xunion_declarations": [],
"declaration_order": [
"fidl.test.json/Simple"
],
@@ -264,6 +265,7 @@
],
"table_declarations": [],
"union_declarations": [],
+ "xunion_declarations": [],
"declaration_order": [
"fidl.test.json/Empty",
"fidl.test.json/EmptyInterface"
@@ -344,6 +346,7 @@
}
],
"union_declarations": [],
+ "xunion_declarations": [],
"declaration_order": [
"fidl.test.json/Simple"
],
@@ -474,6 +477,7 @@
"max_handles": 0
}
],
+ "xunion_declarations": [],
"declaration_order": [
"fidl.test.json/Pizza",
"fidl.test.json/Pasta",
@@ -491,6 +495,78 @@
END_TEST;
}
+bool json_generator_test_xunion() {
+ BEGIN_TEST;
+
+ for (int i = 0; i < kRepeatTestCount; i++) {
+ EXPECT_TRUE(checkJSONGenerator(R"FIDL(
+library fidl.test.json;
+
+xunion xu {
+ string s;
+ int32 i;
+};
+
+)FIDL",
+ R"JSON(
+{
+ "version": "0.0.1",
+ "name": "fidl.test.json",
+ "library_dependencies": [],
+ "const_declarations": [],
+ "enum_declarations": [],
+ "interface_declarations": [],
+ "struct_declarations": [],
+ "table_declarations": [],
+ "union_declarations": [],
+ "xunion_declarations": [
+ {
+ "name": "fidl.test.json/xu",
+ "members": [
+ {
+ "ordinal": 730795057,
+ "type": {
+ "kind": "string",
+ "nullable": false
+ },
+ "name": "s",
+ "size": 16,
+ "max_out_of_line": 4294967295,
+ "alignment": 8,
+ "offset": 0
+ },
+ {
+ "ordinal": 243975053,
+ "type": {
+ "kind": "primitive",
+ "subtype": "int32"
+ },
+ "name": "i",
+ "size": 4,
+ "max_out_of_line": 0,
+ "alignment": 4,
+ "offset": 0
+ }
+ ],
+ "size": 24,
+ "max_out_of_line": 4294967295,
+ "alignment": 8,
+ "max_handles": 0
+ }
+ ],
+ "declaration_order": [
+ "fidl.test.json/xu"
+ ],
+ "declarations": {
+ "fidl.test.json/xu": "xunion"
+ }
+}
+)JSON"));
+ }
+
+ END_TEST;
+}
+
// This test ensures that inherited methods have the same ordinal / signature /
// etc as the method from which they are inheriting.
bool json_generator_test_inheritance() {
@@ -614,6 +690,7 @@
"struct_declarations": [],
"table_declarations": [],
"union_declarations": [],
+ "xunion_declarations": [],
"declaration_order": [
"fidl.test.json/super",
"fidl.test.json/sub"
@@ -744,6 +821,7 @@
"struct_declarations": [],
"table_declarations": [],
"union_declarations": [],
+ "xunion_declarations": [],
"declaration_order": [
"fidl.test.json/Parent",
"fidl.test.json/Child"
@@ -764,6 +842,7 @@
RUN_TEST(json_generator_test_struct);
RUN_TEST(json_generator_test_table);
RUN_TEST(json_generator_test_union);
+RUN_TEST(json_generator_test_xunion);
RUN_TEST(json_generator_test_inheritance);
RUN_TEST(json_generator_test_inheritance_with_recursive_decl);
END_TEST_CASE(json_generator_tests);
diff --git a/system/utest/fidl-compiler/max_bytes_tests.cpp b/system/utest/fidl-compiler/max_bytes_tests.cpp
index 7c26e36..717191d 100644
--- a/system/utest/fidl-compiler/max_bytes_tests.cpp
+++ b/system/utest/fidl-compiler/max_bytes_tests.cpp
@@ -168,10 +168,44 @@
1: array<int64>:5 a;
};
+xunion EmptyXUnion {
+};
+
+xunion XUnionWithOneBool {
+ bool b;
+};
+
+xunion XUnionWithBoolAndU32 {
+ bool b;
+ uint32 u;
+};
+
+xunion XUnionWithBoundedOutOfLineObject {
+ // smaller than |v| below, so will not be selected for max-out-of-line
+ // calculation.
+ bool b;
+
+ // 1. vector<int32>:5 = 20 bytes
+ // = 24 bytes for 8-byte boundary alignment
+ // + 8 bytes for vector element count
+ // + 8 bytes for data pointer
+ // = 40 bytes total
+ // 1. vector<vector<int32>:5>:6 = vector<int32>:5 (40) * 6
+ // = 240 bytes
+ // + 8 bytes for vector element count
+ // + 8 bytes for data pointer
+ // = 256 bytes total
+ vector<vector<int32>:5>:6 v;
+};
+
+xunion XUnionWithUnboundedOutOfLineObject {
+ string s;
+};
+
)FIDL") {}
};
-static bool simple_structs(void) {
+static bool simple_structs() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -200,7 +234,7 @@
END_TEST;
}
-static bool simple_tables(void) {
+static bool simple_tables() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -229,7 +263,7 @@
END_TEST;
}
-static bool optional_structs(void) {
+static bool optional_structs() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -258,7 +292,7 @@
END_TEST;
}
-static bool optional_tables(void) {
+static bool optional_tables() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -307,7 +341,7 @@
END_TEST;
}
-static bool unions(void) {
+static bool unions() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -331,7 +365,7 @@
END_TEST;
}
-static bool vectors(void) {
+static bool vectors() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -370,7 +404,7 @@
END_TEST;
}
-static bool strings(void) {
+static bool strings() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -399,7 +433,7 @@
END_TEST;
}
-static bool arrays(void) {
+static bool arrays() {
BEGIN_TEST;
MaxBytesLibrary test_library;
@@ -418,6 +452,33 @@
END_TEST;
}
+static bool xunions() {
+ BEGIN_TEST;
+
+ MaxBytesLibrary test_library;
+ EXPECT_TRUE(test_library.Compile());
+
+ auto empty = test_library.LookupXUnion("EmptyXUnion");
+ EXPECT_EQ(empty->typeshape.Size(), 24);
+ EXPECT_EQ(empty->typeshape.MaxOutOfLine(), 0);
+
+ auto one_bool = test_library.LookupXUnion("XUnionWithOneBool");
+ EXPECT_EQ(one_bool->typeshape.Size(), 24);
+ EXPECT_EQ(one_bool->typeshape.MaxOutOfLine(), 8);
+
+ auto xu = test_library.LookupXUnion("XUnionWithBoundedOutOfLineObject");
+ EXPECT_EQ(xu->typeshape.Size(), 24);
+ EXPECT_EQ(xu->typeshape.MaxOutOfLine(), 256);
+
+ auto unbounded = test_library.LookupXUnion("XUnionWithUnboundedOutOfLineObject");
+ EXPECT_EQ(unbounded->typeshape.Size(), 24);
+ EXPECT_EQ(unbounded->typeshape.MaxOutOfLine(), std::numeric_limits<uint32_t>::max());
+
+ // TODO(apang): More tests here
+
+ END_TEST;
+}
+
} // namespace
BEGIN_TEST_CASE(max_bytes_tests);
@@ -429,4 +490,5 @@
RUN_TEST(vectors);
RUN_TEST(strings);
RUN_TEST(arrays);
+RUN_TEST(xunions);
END_TEST_CASE(max_bytes_tests);
diff --git a/system/utest/fidl-compiler/rules.mk b/system/utest/fidl-compiler/rules.mk
index a5a162e..1f2a4ca 100644
--- a/system/utest/fidl-compiler/rules.mk
+++ b/system/utest/fidl-compiler/rules.mk
@@ -81,6 +81,7 @@
$(LOCAL_DIR)/types_tests.cpp \
$(LOCAL_DIR)/using_tests.cpp \
$(LOCAL_DIR)/visitor_unittests.cpp \
+ $(LOCAL_DIR)/xunion_tests.cpp \
$(BUILDGEN_DIR)/examples.cpp \
MODULE_COMPILEFLAGS := \
diff --git a/system/utest/fidl-compiler/test_library.h b/system/utest/fidl-compiler/test_library.h
index 3348cc4..e7cdb75 100644
--- a/system/utest/fidl-compiler/test_library.h
+++ b/system/utest/fidl-compiler/test_library.h
@@ -101,6 +101,15 @@
return nullptr;
}
+ const fidl::flat::XUnion* LookupXUnion(const std::string& name) {
+ for (const auto& xunion_decl : library_->xunion_declarations_) {
+ if (xunion_decl->GetName() == name) {
+ return xunion_decl.get();
+ }
+ }
+ return nullptr;
+ }
+
const fidl::flat::Interface* LookupInterface(const std::string& name) {
for (const auto& interface_decl : library_->interface_declarations_) {
if (interface_decl->GetName() == name) {
diff --git a/system/utest/fidl-compiler/xunion_tests.cpp b/system/utest/fidl-compiler/xunion_tests.cpp
new file mode 100644
index 0000000..be84725
--- /dev/null
+++ b/system/utest/fidl-compiler/xunion_tests.cpp
@@ -0,0 +1,77 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <unittest/unittest.h>
+
+#include <fidl/flat_ast.h>
+#include <fidl/lexer.h>
+#include <fidl/parser.h>
+#include <fidl/source_file.h>
+
+#include "test_library.h"
+
+namespace {
+
+static bool Compiles(const std::string& source_code) {
+ return TestLibrary("test.fidl", source_code).Compile();
+}
+
+static bool compiling() {
+ BEGIN_TEST;
+
+ // Populated fields.
+ EXPECT_TRUE(Compiles(R"FIDL(
+library fidl.test.xunions;
+
+xunion Foo {
+ int64 i;
+};
+)FIDL"));
+
+ // Empty xunions are allowed.
+ EXPECT_TRUE(Compiles(R"FIDL(
+library fidl.test.xunions;
+
+xunion Foo {
+};
+)FIDL"));
+
+ // Explicit ordinals are invalid.
+ EXPECT_FALSE(Compiles(R"FIDL(
+library fidl.test.xunions;
+
+xunion Foo {
+ 1: int64 x;
+};
+)FIDL"));
+
+ // Attributes on fields.
+ EXPECT_TRUE(Compiles(R"FIDL(
+library fidl.test.xunions;
+
+xunion Foo {
+ [FooAttr="bar"] int64 x;
+ [BarAttr] bool bar;
+};
+)FIDL"));
+
+ // Attributes on xunions.
+ EXPECT_TRUE(Compiles(R"FIDL(
+library fidl.test.xunions;
+
+[FooAttr="bar"]
+xunion Foo {
+ int64 x;
+ bool please;
+};
+)FIDL"));
+
+ END_TEST;
+}
+
+} // namespace
+
+BEGIN_TEST_CASE(xunion_tests);
+RUN_TEST(compiling);
+END_TEST_CASE(xunion_tests);
diff --git a/system/utest/fidl/abi_tests.cpp b/system/utest/fidl/abi_tests.cpp
index 16c7a0d..c90dc8c 100644
--- a/system/utest/fidl/abi_tests.cpp
+++ b/system/utest/fidl/abi_tests.cpp
@@ -12,7 +12,7 @@
// All the data in coding tables should be pure data.
static_assert(std::is_standard_layout<fidl_type>::value, "");
-static_assert(std::is_standard_layout<FidlField>::value, "");
+static_assert(std::is_standard_layout<FidlStructField>::value, "");
static_assert(std::is_standard_layout<FidlTableField>::value, "");
static_assert(std::is_standard_layout<FidlTypeTag>::value, "");
static_assert(std::is_standard_layout<FidlCodedStruct>::value, "");
diff --git a/system/utest/fidl/fidl_coded_types.cpp b/system/utest/fidl/fidl_coded_types.cpp
index 758ce44..530ff87 100644
--- a/system/utest/fidl/fidl_coded_types.cpp
+++ b/system/utest/fidl/fidl_coded_types.cpp
@@ -92,31 +92,31 @@
fidl::FidlCodedVector(nullptr, 2, sizeof(uint32_t), fidl::kNullable));
// Handle messages.
-static const fidl::FidlField nonnullable_handle_message_fields[] = {
- fidl::FidlField(&nonnullable_handle,
- offsetof(nonnullable_handle_message_layout, inline_struct.handle)),
+static const fidl::FidlStructField nonnullable_handle_message_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle,
+ offsetof(nonnullable_handle_message_layout, inline_struct.handle)),
};
const fidl_type_t nonnullable_handle_message_type = fidl_type_t(fidl::FidlCodedStruct(
nonnullable_handle_message_fields, ArrayCount(nonnullable_handle_message_fields),
sizeof(nonnullable_handle_inline_data),
"nonnullable_handle_message"));
-static const fidl::FidlField multiple_nonnullable_handles_fields[] = {
- fidl::FidlField(&nonnullable_handle,
- offsetof(multiple_nonnullable_handles_message_layout, inline_struct.handle_0)),
- fidl::FidlField(&nonnullable_channel_handle,
- offsetof(multiple_nonnullable_handles_message_layout, inline_struct.handle_1)),
- fidl::FidlField(&nonnullable_vmo_handle,
- offsetof(multiple_nonnullable_handles_message_layout, inline_struct.handle_2)),
+static const fidl::FidlStructField multiple_nonnullable_handles_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle,
+ offsetof(multiple_nonnullable_handles_message_layout, inline_struct.handle_0)),
+ fidl::FidlStructField(&nonnullable_channel_handle,
+ offsetof(multiple_nonnullable_handles_message_layout, inline_struct.handle_1)),
+ fidl::FidlStructField(&nonnullable_vmo_handle,
+ offsetof(multiple_nonnullable_handles_message_layout, inline_struct.handle_2)),
};
const fidl_type_t multiple_nonnullable_handles_message_type = fidl_type_t(fidl::FidlCodedStruct(
multiple_nonnullable_handles_fields, ArrayCount(multiple_nonnullable_handles_fields),
sizeof(multiple_nonnullable_handles_inline_data),
"multiple_nonnullable_handles_message"));
-static const fidl::FidlField nullable_handle_fields[] = {
- fidl::FidlField(&nullable_handle,
- offsetof(nullable_handle_message_layout, inline_struct.handle)),
+static const fidl::FidlStructField nullable_handle_fields[] = {
+ fidl::FidlStructField(&nullable_handle,
+ offsetof(nullable_handle_message_layout, inline_struct.handle)),
};
const fidl_type_t nullable_handle_message_type =
@@ -124,13 +124,13 @@
sizeof(nullable_handle_inline_data),
"nullable_handle_message"));
-static const fidl::FidlField multiple_nullable_handles_fields[] = {
- fidl::FidlField(&nullable_handle,
- offsetof(multiple_nullable_handles_message_layout, inline_struct.handle_0)),
- fidl::FidlField(&nullable_channel_handle,
- offsetof(multiple_nullable_handles_message_layout, inline_struct.handle_1)),
- fidl::FidlField(&nullable_vmo_handle,
- offsetof(multiple_nullable_handles_message_layout, inline_struct.handle_2)),
+static const fidl::FidlStructField multiple_nullable_handles_fields[] = {
+ fidl::FidlStructField(&nullable_handle,
+ offsetof(multiple_nullable_handles_message_layout, inline_struct.handle_0)),
+ fidl::FidlStructField(&nullable_channel_handle,
+ offsetof(multiple_nullable_handles_message_layout, inline_struct.handle_1)),
+ fidl::FidlStructField(&nullable_vmo_handle,
+ offsetof(multiple_nullable_handles_message_layout, inline_struct.handle_2)),
};
const fidl_type_t multiple_nullable_handles_message_type = fidl_type_t(fidl::FidlCodedStruct(
multiple_nullable_handles_fields, ArrayCount(multiple_nullable_handles_fields),
@@ -138,26 +138,26 @@
"multiple_nullable_handles_message"));
// Array messages.
-static const fidl::FidlField array_of_nonnullable_handles_fields[] = {
- fidl::FidlField(&array_of_four_nonnullable_handles,
- offsetof(array_of_nonnullable_handles_message_layout, inline_struct.handles)),
+static const fidl::FidlStructField array_of_nonnullable_handles_fields[] = {
+ fidl::FidlStructField(&array_of_four_nonnullable_handles,
+ offsetof(array_of_nonnullable_handles_message_layout, inline_struct.handles)),
};
const fidl_type_t array_of_nonnullable_handles_message_type = fidl_type_t(fidl::FidlCodedStruct(
array_of_nonnullable_handles_fields, ArrayCount(array_of_nonnullable_handles_fields),
sizeof(array_of_nonnullable_handles_inline_data),
"array_of_nonnullable_handles_message"));
-static const fidl::FidlField array_of_nullable_handles_fields[] = {
- fidl::FidlField(&array_of_five_nullable_handles,
- offsetof(array_of_nullable_handles_message_layout, inline_struct.handles)),
+static const fidl::FidlStructField array_of_nullable_handles_fields[] = {
+ fidl::FidlStructField(&array_of_five_nullable_handles,
+ offsetof(array_of_nullable_handles_message_layout, inline_struct.handles)),
};
const fidl_type_t array_of_nullable_handles_message_type = fidl_type_t(fidl::FidlCodedStruct(
array_of_nullable_handles_fields, ArrayCount(array_of_nullable_handles_fields),
sizeof(array_of_nullable_handles_inline_data),
"array_of_nullable_handles_message"));
-static const fidl::FidlField array_of_array_of_nonnullable_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField array_of_array_of_nonnullable_handles_fields[] = {
+ fidl::FidlStructField(
&array_of_three_arrays_of_four_nonnullable_handles,
offsetof(array_of_array_of_nonnullable_handles_message_layout, inline_struct.handles)),
};
@@ -167,9 +167,9 @@
sizeof(array_of_array_of_nonnullable_handles_inline_data),
"array_of_array_of_nonnullable_handles_message"));
-static const fidl::FidlField out_of_line_fields[] = {
- fidl::FidlField(&array_of_four_nonnullable_handles,
- offsetof(array_of_nonnullable_handles, handles)),
+static const fidl::FidlStructField out_of_line_fields[] = {
+ fidl::FidlStructField(&array_of_four_nonnullable_handles,
+ offsetof(array_of_nonnullable_handles, handles)),
};
static const fidl_type_t out_of_line_type = fidl_type_t(fidl::FidlCodedStruct(
@@ -178,10 +178,10 @@
static const fidl_type_t out_of_line_pointer_type =
fidl_type_t(fidl::FidlCodedStructPointer(&out_of_line_type.coded_struct));
-static const fidl::FidlField out_of_line_array_of_nonnullable_handles_fields[] = {
- fidl::FidlField(&out_of_line_pointer_type,
- offsetof(out_of_line_array_of_nonnullable_handles_message_layout,
- inline_struct.maybe_array)),
+static const fidl::FidlStructField out_of_line_array_of_nonnullable_handles_fields[] = {
+ fidl::FidlStructField(&out_of_line_pointer_type,
+ offsetof(out_of_line_array_of_nonnullable_handles_message_layout,
+ inline_struct.maybe_array)),
};
const fidl_type_t out_of_line_array_of_nonnullable_handles_message_type = fidl_type_t(
fidl::FidlCodedStruct(out_of_line_array_of_nonnullable_handles_fields,
@@ -190,9 +190,9 @@
"out_of_line_array_of_nonnullable_handles_message"));
// String messages.
-static const fidl::FidlField unbounded_nonnullable_string_fields[] = {
- fidl::FidlField(&unbounded_nonnullable_string,
- offsetof(unbounded_nonnullable_string_message_layout, inline_struct.string)),
+static const fidl::FidlStructField unbounded_nonnullable_string_fields[] = {
+ fidl::FidlStructField(&unbounded_nonnullable_string,
+ offsetof(unbounded_nonnullable_string_message_layout, inline_struct.string)),
};
const fidl_type_t unbounded_nonnullable_string_message_type = fidl_type_t(fidl::FidlCodedStruct(
@@ -200,9 +200,9 @@
sizeof(unbounded_nonnullable_string_inline_data),
"unbounded_nonnullable_string_message"));
-static const fidl::FidlField unbounded_nullable_string_fields[] = {
- fidl::FidlField(&unbounded_nullable_string,
- offsetof(unbounded_nullable_string_message_layout, inline_struct.string)),
+static const fidl::FidlStructField unbounded_nullable_string_fields[] = {
+ fidl::FidlStructField(&unbounded_nullable_string,
+ offsetof(unbounded_nullable_string_message_layout, inline_struct.string)),
};
const fidl_type_t unbounded_nullable_string_message_type = fidl_type_t(fidl::FidlCodedStruct(
@@ -210,9 +210,9 @@
sizeof(unbounded_nullable_string_inline_data),
"unbounded_nullable_string_message"));
-static const fidl::FidlField bounded_32_nonnullable_string_fields[] = {
- fidl::FidlField(&bounded_32_nonnullable_string,
- offsetof(bounded_32_nonnullable_string_message_layout, inline_struct.string)),
+static const fidl::FidlStructField bounded_32_nonnullable_string_fields[] = {
+ fidl::FidlStructField(&bounded_32_nonnullable_string,
+ offsetof(bounded_32_nonnullable_string_message_layout, inline_struct.string)),
};
const fidl_type_t bounded_32_nonnullable_string_message_type = fidl_type_t(fidl::FidlCodedStruct(
@@ -220,45 +220,45 @@
sizeof(bounded_32_nonnullable_string_inline_data),
"bounded_32_nonnullable_string_message"));
-static const fidl::FidlField bounded_32_nullable_string_fields[] = {
- fidl::FidlField(&bounded_32_nullable_string,
- offsetof(bounded_32_nullable_string_message_layout, inline_struct.string)),
+static const fidl::FidlStructField bounded_32_nullable_string_fields[] = {
+ fidl::FidlStructField(&bounded_32_nullable_string,
+ offsetof(bounded_32_nullable_string_message_layout, inline_struct.string)),
};
const fidl_type_t bounded_32_nullable_string_message_type = fidl_type_t(fidl::FidlCodedStruct(
bounded_32_nullable_string_fields, ArrayCount(bounded_32_nullable_string_fields),
sizeof(bounded_32_nullable_string_inline_data),
"bounded_32_nullable_string_message"));
-static const fidl::FidlField multiple_nonnullable_strings_fields[] = {
- fidl::FidlField(&bounded_32_nonnullable_string,
- offsetof(multiple_nonnullable_strings_message_layout, inline_struct.string)),
+static const fidl::FidlStructField multiple_nonnullable_strings_fields[] = {
+ fidl::FidlStructField(&bounded_32_nonnullable_string,
+ offsetof(multiple_nonnullable_strings_message_layout, inline_struct.string)),
- fidl::FidlField(&bounded_32_nonnullable_string,
- offsetof(multiple_nonnullable_strings_message_layout, inline_struct.string2)),
+ fidl::FidlStructField(&bounded_32_nonnullable_string,
+ offsetof(multiple_nonnullable_strings_message_layout, inline_struct.string2)),
};
const fidl_type_t multiple_nonnullable_strings_message_type = fidl_type_t(fidl::FidlCodedStruct(
multiple_nonnullable_strings_fields, ArrayCount(multiple_nonnullable_strings_fields),
sizeof(multiple_nonnullable_strings_inline_data),
"multiple_nonnullable_strings_message"));
-static const fidl::FidlField multiple_nullable_strings_fields[] = {
- fidl::FidlField(&bounded_32_nullable_string,
- offsetof(multiple_nullable_strings_message_layout, inline_struct.string)),
+static const fidl::FidlStructField multiple_nullable_strings_fields[] = {
+ fidl::FidlStructField(&bounded_32_nullable_string,
+ offsetof(multiple_nullable_strings_message_layout, inline_struct.string)),
- fidl::FidlField(&bounded_32_nullable_string,
- offsetof(multiple_nullable_strings_message_layout, inline_struct.string2)),
+ fidl::FidlStructField(&bounded_32_nullable_string,
+ offsetof(multiple_nullable_strings_message_layout, inline_struct.string2)),
};
const fidl_type_t multiple_nullable_strings_message_type = fidl_type_t(fidl::FidlCodedStruct(
multiple_nullable_strings_fields, ArrayCount(multiple_nullable_strings_fields),
sizeof(multiple_nullable_strings_inline_data),
"multiple_nullable_strings_message"));
-static const fidl::FidlField multiple_short_nonnullable_strings_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField multiple_short_nonnullable_strings_fields[] = {
+ fidl::FidlStructField(
&bounded_4_nonnullable_string,
offsetof(multiple_short_nonnullable_strings_message_layout, inline_struct.string)),
- fidl::FidlField(
+ fidl::FidlStructField(
&bounded_32_nonnullable_string,
offsetof(multiple_short_nonnullable_strings_message_layout, inline_struct.string2)),
};
@@ -268,11 +268,11 @@
sizeof(multiple_short_nonnullable_strings_inline_data),
"multiple_short_nonnullable_strings_message"));
-static const fidl::FidlField multiple_short_nullable_strings_fields[] = {
- fidl::FidlField(&bounded_4_nullable_string,
- offsetof(multiple_short_nullable_strings_message_layout, inline_struct.string)),
+static const fidl::FidlStructField multiple_short_nullable_strings_fields[] = {
+ fidl::FidlStructField(&bounded_4_nullable_string,
+ offsetof(multiple_short_nullable_strings_message_layout, inline_struct.string)),
- fidl::FidlField(
+ fidl::FidlStructField(
&bounded_32_nullable_string,
offsetof(multiple_short_nullable_strings_message_layout, inline_struct.string2)),
};
@@ -282,8 +282,8 @@
"multiple_short_nullable_strings_message"));
// Vector messages.
-static const fidl::FidlField unbounded_nonnullable_vector_of_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField unbounded_nonnullable_vector_of_handles_fields[] = {
+ fidl::FidlStructField(
&unbounded_nonnullable_vector_of_handles,
offsetof(unbounded_nonnullable_vector_of_handles_message_layout, inline_struct.vector)),
@@ -294,8 +294,8 @@
sizeof(unbounded_nonnullable_vector_of_handles_inline_data),
"unbounded_nonnullable_vector_of_handles_message"));
-static const fidl::FidlField unbounded_nullable_vector_of_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField unbounded_nullable_vector_of_handles_fields[] = {
+ fidl::FidlStructField(
&unbounded_nullable_vector_of_handles,
offsetof(unbounded_nullable_vector_of_handles_message_layout, inline_struct.vector)),
@@ -306,8 +306,8 @@
sizeof(unbounded_nullable_vector_of_handles_inline_data),
"unbounded_nullable_vector_of_handles_message"));
-static const fidl::FidlField bounded_32_nonnullable_vector_of_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField bounded_32_nonnullable_vector_of_handles_fields[] = {
+ fidl::FidlStructField(
&bounded_32_nonnullable_vector_of_handles,
offsetof(bounded_32_nonnullable_vector_of_handles_message_layout, inline_struct.vector)),
@@ -318,8 +318,8 @@
sizeof(bounded_32_nonnullable_vector_of_handles_inline_data),
"bounded_32_nonnullable_vector_of_handles_message"));
-static const fidl::FidlField bounded_32_nullable_vector_of_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField bounded_32_nullable_vector_of_handles_fields[] = {
+ fidl::FidlStructField(
&bounded_32_nullable_vector_of_handles,
offsetof(bounded_32_nullable_vector_of_handles_message_layout, inline_struct.vector)),
@@ -330,11 +330,11 @@
sizeof(bounded_32_nullable_vector_of_handles_inline_data),
"bounded_32_nullable_vector_of_handles_message"));
-static const fidl::FidlField multiple_nonnullable_vectors_of_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField multiple_nonnullable_vectors_of_handles_fields[] = {
+ fidl::FidlStructField(
&bounded_2_nonnullable_vector_of_handles,
offsetof(multiple_nonnullable_vectors_of_handles_message_layout, inline_struct.vector)),
- fidl::FidlField(
+ fidl::FidlStructField(
&unbounded_nonnullable_vector_of_handles,
offsetof(multiple_nonnullable_vectors_of_handles_message_layout, inline_struct.vector2)),
};
@@ -344,11 +344,11 @@
sizeof(multiple_nonnullable_vectors_of_handles_inline_data),
"multiple_nonnullable_vectors_of_handles_message"));
-static const fidl::FidlField multiple_nullable_vectors_of_handles_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField multiple_nullable_vectors_of_handles_fields[] = {
+ fidl::FidlStructField(
&bounded_2_nullable_vector_of_handles,
offsetof(multiple_nullable_vectors_of_handles_message_layout, inline_struct.vector)),
- fidl::FidlField(
+ fidl::FidlStructField(
&unbounded_nullable_vector_of_handles,
offsetof(multiple_nullable_vectors_of_handles_message_layout, inline_struct.vector2)),
};
@@ -358,8 +358,8 @@
sizeof(multiple_nullable_vectors_of_handles_inline_data),
"multiple_nullable_vectors_of_handles_message"));
-static const fidl::FidlField unbounded_nonnullable_vector_of_uint32_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField unbounded_nonnullable_vector_of_uint32_fields[] = {
+ fidl::FidlStructField(
&unbounded_nonnullable_vector_of_uint32,
offsetof(unbounded_nonnullable_vector_of_uint32_message_layout, inline_struct.vector)),
@@ -370,8 +370,8 @@
sizeof(unbounded_nonnullable_vector_of_uint32_inline_data),
"unbounded_nonnullable_vector_of_uint32_message"));
-static const fidl::FidlField unbounded_nullable_vector_of_uint32_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField unbounded_nullable_vector_of_uint32_fields[] = {
+ fidl::FidlStructField(
&unbounded_nullable_vector_of_uint32,
offsetof(unbounded_nullable_vector_of_uint32_message_layout, inline_struct.vector)),
@@ -382,8 +382,8 @@
sizeof(unbounded_nullable_vector_of_uint32_inline_data),
"unbounded_nullable_vector_of_uint32_message"));
-static const fidl::FidlField bounded_32_nonnullable_vector_of_uint32_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField bounded_32_nonnullable_vector_of_uint32_fields[] = {
+ fidl::FidlStructField(
&bounded_32_nonnullable_vector_of_uint32,
offsetof(bounded_32_nonnullable_vector_of_uint32_message_layout, inline_struct.vector)),
@@ -394,8 +394,8 @@
sizeof(bounded_32_nonnullable_vector_of_uint32_inline_data),
"bounded_32_nonnullable_vector_of_uint32_message"));
-static const fidl::FidlField bounded_32_nullable_vector_of_uint32_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField bounded_32_nullable_vector_of_uint32_fields[] = {
+ fidl::FidlStructField(
&bounded_32_nullable_vector_of_uint32,
offsetof(bounded_32_nullable_vector_of_uint32_message_layout, inline_struct.vector)),
@@ -406,11 +406,11 @@
sizeof(bounded_32_nullable_vector_of_uint32_inline_data),
"bounded_32_nullable_vector_of_uint32_message"));
-static const fidl::FidlField multiple_nonnullable_vectors_of_uint32_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField multiple_nonnullable_vectors_of_uint32_fields[] = {
+ fidl::FidlStructField(
&bounded_2_nonnullable_vector_of_uint32,
offsetof(multiple_nonnullable_vectors_of_uint32_message_layout, inline_struct.vector)),
- fidl::FidlField(
+ fidl::FidlStructField(
&unbounded_nonnullable_vector_of_uint32,
offsetof(multiple_nonnullable_vectors_of_uint32_message_layout, inline_struct.vector2)),
};
@@ -420,11 +420,11 @@
sizeof(multiple_nonnullable_vectors_of_uint32_inline_data),
"multiple_nonnullable_vectors_of_uint32_message"));
-static const fidl::FidlField multiple_nullable_vectors_of_uint32_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField multiple_nullable_vectors_of_uint32_fields[] = {
+ fidl::FidlStructField(
&bounded_2_nullable_vector_of_uint32,
offsetof(multiple_nullable_vectors_of_uint32_message_layout, inline_struct.vector)),
- fidl::FidlField(
+ fidl::FidlStructField(
&unbounded_nullable_vector_of_uint32,
offsetof(multiple_nullable_vectors_of_uint32_message_layout, inline_struct.vector2)),
};
@@ -444,9 +444,9 @@
offsetof(nonnullable_handle_union, handle),
sizeof(nonnullable_handle_union),
"nonnullable_handle_union"));
-static const fidl::FidlField nonnullable_handle_union_fields[] = {
- fidl::FidlField(&nonnullable_handle_union_type,
- offsetof(nonnullable_handle_union_message_layout, inline_struct.data)),
+static const fidl::FidlStructField nonnullable_handle_union_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle_union_type,
+ offsetof(nonnullable_handle_union_message_layout, inline_struct.data)),
};
const fidl_type_t nonnullable_handle_union_message_type = fidl_type_t(fidl::FidlCodedStruct(
nonnullable_handle_union_fields, ArrayCount(nonnullable_handle_union_fields),
@@ -464,8 +464,8 @@
offsetof(array_of_nonnullable_handles_union, handle),
sizeof(array_of_nonnullable_handles_union),
"array_of_nonnullable_handles_union"));
-static const fidl::FidlField array_of_nonnullable_handles_union_fields[] = {
- fidl::FidlField(
+static const fidl::FidlStructField array_of_nonnullable_handles_union_fields[] = {
+ fidl::FidlStructField(
&array_of_nonnullable_handles_union_type,
offsetof(array_of_nonnullable_handles_union_message_layout, inline_struct.data)),
@@ -479,9 +479,9 @@
// Union pointer messages.
const fidl_type_t nonnullable_handle_union_ptr =
fidl_type_t(fidl::FidlCodedUnionPointer(&nonnullable_handle_union_type.coded_union));
-static const fidl::FidlField nonnullable_handle_union_ptr_fields[] = {
- fidl::FidlField(&nonnullable_handle_union_ptr,
- offsetof(nonnullable_handle_union_ptr_inline_data, data)),
+static const fidl::FidlStructField nonnullable_handle_union_ptr_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle_union_ptr,
+ offsetof(nonnullable_handle_union_ptr_inline_data, data)),
};
const fidl_type_t nonnullable_handle_union_ptr_message_type = fidl_type_t(fidl::FidlCodedStruct(
nonnullable_handle_union_ptr_fields, ArrayCount(nonnullable_handle_union_ptr_fields),
@@ -490,9 +490,9 @@
static const fidl_type_t array_of_nonnullable_handles_union_ptr =
fidl_type_t(fidl::FidlCodedUnionPointer(&array_of_nonnullable_handles_union_type.coded_union));
-static const fidl::FidlField array_of_nonnullable_handles_union_ptr_fields[] = {
- fidl::FidlField(&array_of_nonnullable_handles_union_ptr,
- offsetof(array_of_nonnullable_handles_union_ptr_inline_data, data)),
+static const fidl::FidlStructField array_of_nonnullable_handles_union_ptr_fields[] = {
+ fidl::FidlStructField(&array_of_nonnullable_handles_union_ptr,
+ offsetof(array_of_nonnullable_handles_union_ptr_inline_data, data)),
};
const fidl_type_t array_of_nonnullable_handles_union_ptr_message_type =
fidl_type_t(fidl::FidlCodedStruct(array_of_nonnullable_handles_union_ptr_fields,
@@ -501,36 +501,36 @@
"array_of_nonnullable_handles_union_ptr_message"));
// Struct messages.
-static const fidl::FidlField struct_level_3_fields[] = {
- fidl::FidlField(&nonnullable_handle, offsetof(struct_level_3, handle_3)),
+static const fidl::FidlStructField struct_level_3_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_level_3, handle_3)),
};
static const fidl_type_t struct_level_3_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_level_3_fields, ArrayCount(struct_level_3_fields), sizeof(struct_level_3),
"struct_level_3"));
-static const fidl::FidlField struct_level_2_fields[] = {
- fidl::FidlField(&struct_level_3_struct, offsetof(struct_level_2, l3)),
- fidl::FidlField(&nonnullable_handle, offsetof(struct_level_2, handle_2)),
+static const fidl::FidlStructField struct_level_2_fields[] = {
+ fidl::FidlStructField(&struct_level_3_struct, offsetof(struct_level_2, l3)),
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_level_2, handle_2)),
};
static const fidl_type_t struct_level_2_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_level_2_fields, ArrayCount(struct_level_2_fields), sizeof(struct_level_2),
"struct_level_2"));
-static const fidl::FidlField struct_level_1_fields[] = {
- fidl::FidlField(&nonnullable_handle, offsetof(struct_level_1, handle_1)),
- fidl::FidlField(&struct_level_2_struct, offsetof(struct_level_1, l2)),
+static const fidl::FidlStructField struct_level_1_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_level_1, handle_1)),
+ fidl::FidlStructField(&struct_level_2_struct, offsetof(struct_level_1, l2)),
};
static const fidl_type_t struct_level_1_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_level_1_fields, ArrayCount(struct_level_1_fields), sizeof(struct_level_1),
"struct_level_1"));
-static const fidl::FidlField struct_level_0_fields[] = {
- fidl::FidlField(&struct_level_1_struct, offsetof(struct_level_0, l1)),
- fidl::FidlField(&nonnullable_handle, offsetof(struct_level_0, handle_0)),
+static const fidl::FidlStructField struct_level_0_fields[] = {
+ fidl::FidlStructField(&struct_level_1_struct, offsetof(struct_level_0, l1)),
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_level_0, handle_0)),
};
const fidl_type_t struct_level_0_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_level_0_fields, ArrayCount(struct_level_1_fields), sizeof(struct_level_0),
"struct_level_0"));
-static const fidl::FidlField nested_structs_fields[] = {
- fidl::FidlField(&struct_level_0_struct,
- offsetof(nested_structs_message_layout, inline_struct.l0)),
+static const fidl::FidlStructField nested_structs_fields[] = {
+ fidl::FidlStructField(&struct_level_0_struct,
+ offsetof(nested_structs_message_layout, inline_struct.l0)),
};
const fidl_type_t nested_structs_message_type = fidl_type_t(fidl::FidlCodedStruct(
@@ -538,8 +538,8 @@
"nested_structs_message"));
// Struct pointer messages.
-static const fidl::FidlField struct_ptr_level_3_fields[] = {
- fidl::FidlField(&nonnullable_handle, offsetof(struct_ptr_level_3, handle_3)),
+static const fidl::FidlStructField struct_ptr_level_3_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_ptr_level_3, handle_3)),
};
static const fidl_type_t struct_ptr_level_3_struct = fidl_type_t(fidl::FidlCodedStruct(
@@ -547,46 +547,46 @@
"struct_ptr_level_3"));
static const fidl_type_t struct_ptr_level_3_struct_pointer =
fidl_type_t(fidl::FidlCodedStructPointer(&struct_ptr_level_3_struct.coded_struct));
-static const fidl::FidlField struct_ptr_level_2_fields[] = {
- fidl::FidlField(&struct_ptr_level_3_struct_pointer, offsetof(struct_ptr_level_2, l3_present)),
- fidl::FidlField(&struct_ptr_level_3_struct_pointer, offsetof(struct_ptr_level_2, l3_absent)),
- fidl::FidlField(&struct_ptr_level_3_struct, offsetof(struct_ptr_level_2, l3_inline)),
- fidl::FidlField(&nonnullable_handle, offsetof(struct_ptr_level_2, handle_2)),
+static const fidl::FidlStructField struct_ptr_level_2_fields[] = {
+ fidl::FidlStructField(&struct_ptr_level_3_struct_pointer, offsetof(struct_ptr_level_2, l3_present)),
+ fidl::FidlStructField(&struct_ptr_level_3_struct_pointer, offsetof(struct_ptr_level_2, l3_absent)),
+ fidl::FidlStructField(&struct_ptr_level_3_struct, offsetof(struct_ptr_level_2, l3_inline)),
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_ptr_level_2, handle_2)),
};
static const fidl_type_t struct_ptr_level_2_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_ptr_level_2_fields, ArrayCount(struct_ptr_level_2_fields), sizeof(struct_ptr_level_2),
"struct_ptr_level_2"));
static const fidl_type_t struct_ptr_level_2_struct_pointer =
fidl_type_t(fidl::FidlCodedStructPointer(&struct_ptr_level_2_struct.coded_struct));
-static const fidl::FidlField struct_ptr_level_1_fields[] = {
- fidl::FidlField(&nonnullable_handle, offsetof(struct_ptr_level_1, handle_1)),
- fidl::FidlField(&struct_ptr_level_2_struct_pointer, offsetof(struct_ptr_level_1, l2_present)),
- fidl::FidlField(&struct_ptr_level_2_struct, offsetof(struct_ptr_level_1, l2_inline)),
- fidl::FidlField(&struct_ptr_level_2_struct_pointer, offsetof(struct_ptr_level_1, l2_absent)),
+static const fidl::FidlStructField struct_ptr_level_1_fields[] = {
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_ptr_level_1, handle_1)),
+ fidl::FidlStructField(&struct_ptr_level_2_struct_pointer, offsetof(struct_ptr_level_1, l2_present)),
+ fidl::FidlStructField(&struct_ptr_level_2_struct, offsetof(struct_ptr_level_1, l2_inline)),
+ fidl::FidlStructField(&struct_ptr_level_2_struct_pointer, offsetof(struct_ptr_level_1, l2_absent)),
};
static const fidl_type_t struct_ptr_level_1_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_ptr_level_1_fields, ArrayCount(struct_ptr_level_1_fields), sizeof(struct_ptr_level_1),
"struct_ptr_level_1"));
static const fidl_type_t struct_ptr_level_1_struct_pointer =
fidl_type_t(fidl::FidlCodedStructPointer(&struct_ptr_level_1_struct.coded_struct));
-static const fidl::FidlField struct_ptr_level_0_fields[] = {
- fidl::FidlField(&struct_ptr_level_1_struct_pointer, offsetof(struct_ptr_level_0, l1_absent)),
- fidl::FidlField(&struct_ptr_level_1_struct, offsetof(struct_ptr_level_0, l1_inline)),
- fidl::FidlField(&nonnullable_handle, offsetof(struct_ptr_level_0, handle_0)),
- fidl::FidlField(&struct_ptr_level_1_struct_pointer, offsetof(struct_ptr_level_0, l1_present)),
+static const fidl::FidlStructField struct_ptr_level_0_fields[] = {
+ fidl::FidlStructField(&struct_ptr_level_1_struct_pointer, offsetof(struct_ptr_level_0, l1_absent)),
+ fidl::FidlStructField(&struct_ptr_level_1_struct, offsetof(struct_ptr_level_0, l1_inline)),
+ fidl::FidlStructField(&nonnullable_handle, offsetof(struct_ptr_level_0, handle_0)),
+ fidl::FidlStructField(&struct_ptr_level_1_struct_pointer, offsetof(struct_ptr_level_0, l1_present)),
};
static const fidl_type_t struct_ptr_level_0_struct = fidl_type_t(fidl::FidlCodedStruct(
struct_ptr_level_0_fields, ArrayCount(struct_ptr_level_0_fields), sizeof(struct_ptr_level_0),
"struct_ptr_level_0"));
const fidl_type_t struct_ptr_level_0_struct_pointer =
fidl_type_t(fidl::FidlCodedStructPointer(&struct_ptr_level_0_struct.coded_struct));
-static const fidl::FidlField nested_struct_ptrs_fields[] = {
- fidl::FidlField(&struct_ptr_level_0_struct,
- offsetof(nested_struct_ptrs_inline_data, l0_inline)),
- fidl::FidlField(&struct_ptr_level_0_struct_pointer,
- offsetof(nested_struct_ptrs_inline_data, l0_absent)),
- fidl::FidlField(&struct_ptr_level_0_struct_pointer,
- offsetof(nested_struct_ptrs_inline_data, l0_present)),
+static const fidl::FidlStructField nested_struct_ptrs_fields[] = {
+ fidl::FidlStructField(&struct_ptr_level_0_struct,
+ offsetof(nested_struct_ptrs_inline_data, l0_inline)),
+ fidl::FidlStructField(&struct_ptr_level_0_struct_pointer,
+ offsetof(nested_struct_ptrs_inline_data, l0_absent)),
+ fidl::FidlStructField(&struct_ptr_level_0_struct_pointer,
+ offsetof(nested_struct_ptrs_inline_data, l0_present)),
};
const fidl_type_t nested_struct_ptrs_message_type = fidl_type_t(
fidl::FidlCodedStruct(nested_struct_ptrs_fields, ArrayCount(nested_struct_ptrs_fields),
@@ -603,8 +603,8 @@
const fidl_type_t maybe_recurse_type = fidl_type_t(fidl::FidlCodedUnion(
maybe_recurse_union_members, ArrayCount(maybe_recurse_union_members),
offsetof(maybe_recurse, handle), sizeof(maybe_recurse), "maybe_recurse"));
-static const fidl::FidlField recursion_fields[] = {
- fidl::FidlField(&maybe_recurse_type, offsetof(recursion_inline_data, inline_union)),
+static const fidl::FidlStructField recursion_fields[] = {
+ fidl::FidlStructField(&maybe_recurse_type, offsetof(recursion_inline_data, inline_union)),
};
const fidl_type_t recursion_message_type = fidl_type_t(fidl::FidlCodedStruct(
recursion_fields, ArrayCount(recursion_fields), sizeof(recursion_inline_data),
diff --git a/system/utest/fidl/handle_closing_tests.cpp b/system/utest/fidl/handle_closing_tests.cpp
index 57e73c2..46d39a3 100644
--- a/system/utest/fidl/handle_closing_tests.cpp
+++ b/system/utest/fidl/handle_closing_tests.cpp
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include <limits.h>
-#include <stddef.h>
#include <new>
+#include <stddef.h>
#include <lib/fidl/coding.h>
#include <lib/fidl/internal.h>
@@ -269,8 +269,8 @@
const fidl_type_t unbounded_too_large_nullable_vector_of_handles =
fidl_type_t(fidl::FidlCodedVector(&nullable_handle, FIDL_MAX_SIZE, sizeof(zx_handle_t),
fidl::kNullable));
-static const ::fidl::FidlField unbounded_too_large_nullable_vector_of_handles_fields[] = {
- ::fidl::FidlField(
+static const ::fidl::FidlStructField unbounded_too_large_nullable_vector_of_handles_fields[] = {
+ ::fidl::FidlStructField(
&unbounded_too_large_nullable_vector_of_handles,
offsetof(unbounded_too_large_nullable_vector_of_handles_message_layout,
inline_struct.vector)),
diff --git a/system/utest/fidl/llcpp_types_tests.cpp b/system/utest/fidl/llcpp_types_tests.cpp
index 9b60db9..76c3d6e 100644
--- a/system/utest/fidl/llcpp_types_tests.cpp
+++ b/system/utest/fidl/llcpp_types_tests.cpp
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
#include <stdalign.h>
#include <utility>
-#include <memory>
#include <lib/fidl/internal.h>
#include <lib/fidl/llcpp/array_wrapper.h>
@@ -22,7 +22,7 @@
struct NonnullableChannelMessage {
alignas(FIDL_ALIGNMENT)
- fidl_message_header_t header;
+ fidl_message_header_t header;
zx::channel channel;
static constexpr uint32_t MaxNumHandles = 1;
@@ -38,28 +38,28 @@
const fidl_type_t NonnullableChannelType =
fidl_type_t(fidl::FidlCodedHandle(ZX_OBJ_TYPE_CHANNEL, fidl::kNonnullable));
-const fidl::FidlField NonnullableChannelMessageFields[] = {
- fidl::FidlField(&NonnullableChannelType,
- offsetof(NonnullableChannelMessage, channel)),
+const fidl::FidlStructField NonnullableChannelMessageFields[] = {
+ fidl::FidlStructField(&NonnullableChannelType,
+ offsetof(NonnullableChannelMessage, channel)),
};
const fidl_type_t NonnullableChannelMessageType = fidl_type_t(fidl::FidlCodedStruct(
NonnullableChannelMessageFields, /* field_count */ 1,
sizeof(NonnullableChannelMessage),
"NonnullableChannelMessage"));
-}
+} // namespace
namespace fidl {
// Manually specialize the templates.
// These will match the llcpp codegen output.
-template<>
+template <>
struct IsFidlType<NonnullableChannelMessage> : public std::true_type {};
-template<>
+template <>
struct IsFidlMessage<NonnullableChannelMessage> : public std::true_type {};
-}
+} // namespace fidl
namespace {
@@ -67,7 +67,7 @@
// Zircon system call instead of calling a destructor, we indirectly test for handle closure
// via the ZX_ERR_PEER_CLOSED error message.
-bool HelperExpectPeerValid(zx::channel &channel) {
+bool HelperExpectPeerValid(zx::channel& channel) {
BEGIN_HELPER;
const char* foo = "A";
@@ -76,7 +76,7 @@
END_HELPER;
}
-bool HelperExpectPeerInvalid(zx::channel &channel) {
+bool HelperExpectPeerInvalid(zx::channel& channel) {
BEGIN_HELPER;
const char* foo = "A";
@@ -98,8 +98,8 @@
{
fidl::EncodedMessage<NonnullableChannelMessage> encoded_message;
- encoded_message.Initialize([&buf, &channel_1] (fidl::BytePart& msg_bytes,
- fidl::HandlePart& msg_handles) {
+ encoded_message.Initialize([&buf, &channel_1](fidl::BytePart& msg_bytes,
+ fidl::HandlePart& msg_handles) {
msg_bytes = fidl::BytePart(buf, sizeof(buf), sizeof(buf));
zx_handle_t* handle = msg_handles.data();
@@ -169,10 +169,9 @@
new fidl::EncodedMessage<NonnullableChannelMessage>();
zx_handle_t unsafe_handle_backup;
- encoded_message->Initialize([&buf, &channel_1, &unsafe_handle_backup] (
- fidl::BytePart& msg_bytes,
- fidl::HandlePart& msg_handles
- ) {
+ encoded_message->Initialize([&buf, &channel_1, &unsafe_handle_backup](
+ fidl::BytePart& msg_bytes,
+ fidl::HandlePart& msg_handles) {
msg_bytes = fidl::BytePart(buf, sizeof(buf), sizeof(buf));
zx_handle_t* handle = msg_handles.data();
@@ -189,13 +188,12 @@
});
uint8_t golden_encoded[] = {
- 10, 0, 0, 0, // txid
- 0, 0, 0, 0, // reserved
- 0, 0, 0, 0, // flags
- 42, 0, 0, 0, // ordinal
+ 10, 0, 0, 0, // txid
+ 0, 0, 0, 0, // reserved
+ 0, 0, 0, 0, // flags
+ 42, 0, 0, 0, // ordinal
255, 255, 255, 255, // handle present
- 0, 0, 0, 0
- };
+ 0, 0, 0, 0};
// Byte-accurate comparison
EXPECT_EQ(memcmp(golden_encoded, buf, sizeof(buf)), 0);
@@ -254,11 +252,11 @@
END_TEST;
}
-} // namespace
+} // namespace
BEGIN_TEST_CASE(llcpp_types_tests)
- RUN_NAMED_TEST("EncodedMessage test", EncodedMessageTest)
- RUN_NAMED_TEST("DecodedMessage test", DecodedMessageTest)
- RUN_NAMED_TEST("Round trip test", RoundTripTest)
- RUN_NAMED_TEST("Array layout test", ArrayLayoutTest)
+RUN_NAMED_TEST("EncodedMessage test", EncodedMessageTest)
+RUN_NAMED_TEST("DecodedMessage test", DecodedMessageTest)
+RUN_NAMED_TEST("Round trip test", RoundTripTest)
+RUN_NAMED_TEST("Array layout test", ArrayLayoutTest)
END_TEST_CASE(llcpp_types_tests);