Skip to content

Commit

Permalink
add parse-c support for unions
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrk committed Nov 17, 2017
1 parent d108689 commit b50c676
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
26 changes: 18 additions & 8 deletions src/parsec.cpp
Expand Up @@ -680,11 +680,10 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
switch (elaborated_ty->getKeyword()) {
case ETK_Struct:
return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
case ETK_Enum:
case ETK_Union:
return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
case ETK_Interface:
case ETK_Union:
case ETK_Class:
case ETK_Typename:
case ETK_None:
Expand Down Expand Up @@ -2946,15 +2945,24 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {

const char *raw_name = decl_name(record_decl);

if (!record_decl->isStruct()) {
emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct", raw_name);
const char *container_kind_name;
ContainerKind container_kind;
if (record_decl->isUnion()) {
container_kind_name = "union";
container_kind = ContainerKindUnion;
} else if (record_decl->isStruct()) {
container_kind_name = "struct";
container_kind = ContainerKindStruct;
} else {
emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name);
c->decl_table.put(record_decl->getCanonicalDecl(), nullptr);
return nullptr;
}

bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0;
Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
Buf *full_type_name = (bare_name == nullptr) ? nullptr : buf_sprintf("struct_%s", buf_ptr(bare_name));
Buf *full_type_name = (bare_name == nullptr) ?
nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));

RecordDecl *record_def = record_decl->getDefinition();
if (record_def == nullptr) {
Expand All @@ -2970,14 +2978,15 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
const FieldDecl *field_decl = *it;

if (field_decl->isBitField()) {
emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield",
emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
container_kind_name,
is_anonymous ? "(anon)" : buf_ptr(bare_name));
return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
}
}

AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl);
struct_node->data.container_decl.kind = ContainerKindStruct;
struct_node->data.container_decl.kind = container_kind;
struct_node->data.container_decl.layout = ContainerLayoutExtern;

// TODO handle attribute packed
Expand All @@ -3004,7 +3013,8 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {

if (field_node->data.struct_field.type == nullptr) {
emit_warning(c, field_decl->getLocation(),
"struct %s demoted to opaque type - unresolved type",
"%s %s demoted to opaque type - unresolved type",
container_kind_name,
is_anonymous ? "(anon)" : buf_ptr(bare_name));

return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
Expand Down
15 changes: 15 additions & 0 deletions test/parsec.zig
Expand Up @@ -857,6 +857,21 @@ pub fn addCases(cases: &tests.ParseCContext) {
\\ (*(??x)) = 1;
\\}
);

cases.add("simple union",
\\union Foo {
\\ int x;
\\ double y;
\\};
,
\\pub const union_Foo = extern union {
\\ x: c_int,
\\ y: f64,
\\};
,
\\pub const Foo = union_Foo;
);

}


Expand Down

0 comments on commit b50c676

Please sign in to comment.