Commit b50c676f76

Andrew Kelley <superjoe30@gmail.com>
2017-11-17 05:54:33
add parse-c support for unions
1 parent d108689
Changed files (2)
src/parsec.cpp
@@ -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:
@@ -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) {
@@ -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
@@ -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);
test/parsec.zig
@@ -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;
+    );
+
 }