Commit 1053172854

Andrew Kelley <superjoe30@gmail.com>
2016-01-31 23:44:02
parseh handles typedef void better
and introduce c_long_double type
1 parent c77637d
doc/langref.md
@@ -205,6 +205,7 @@ c_long          long                for ABI compatibility with C
 c_ulong         unsigned long       for ABI compatibility with C
 c_longlong      long long           for ABI compatibility with C
 c_ulonglong     unsigned long long  for ABI compatibility with C
+c_long_double   long double         for ABI compatibility with C
 ```
 
 ### Boolean Type
doc/targets.md
@@ -17,3 +17,5 @@ for each target.
 
 Make sure that parseh sends the correct command line parameters to libclang for
 the given target.
+
+Make sure that `c_long_double` codegens the correct floating point value.
src/all_types.hpp
@@ -1023,6 +1023,7 @@ struct CodeGen {
         TypeTableEntry *entry_bool;
         TypeTableEntry *entry_int[2][4]; // [signed,unsigned][8,16,32,64]
         TypeTableEntry *entry_c_int[8];
+        TypeTableEntry *entry_c_long_double;
         TypeTableEntry *entry_u8;
         TypeTableEntry *entry_u16;
         TypeTableEntry *entry_u32;
src/codegen.cpp
@@ -2918,6 +2918,18 @@ static void define_builtin_types(CodeGen *g) {
         g->builtin_types.entry_f64 = entry;
         g->primitive_type_table.put(&entry->name, entry);
     }
+    {
+        TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
+        entry->type_ref = LLVMX86FP80Type();
+        buf_init_from_str(&entry->name, "c_long_double");
+        entry->size_in_bits = 128;
+        entry->align_in_bits = 128;
+        entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name),
+                80, entry->align_in_bits,
+                LLVMZigEncoding_DW_ATE_float());
+        g->builtin_types.entry_c_long_double = entry;
+        g->primitive_type_table.put(&entry->name, entry);
+    }
     {
         TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
         entry->type_ref = LLVMVoidType();
src/parseh.cpp
@@ -234,6 +234,19 @@ static TypeTableEntry *get_c_void_type(Context *c) {
     return c->c_void_type;
 }
 
+static bool is_c_void_type(Context *c, TypeTableEntry *type_entry) {
+    if (!c->c_void_type) {
+        return false;
+    }
+    while (type_entry->id == TypeTableEntryIdTypeDecl) {
+        if (type_entry == c->c_void_type) {
+            return true;
+        }
+        type_entry = type_entry->data.type_decl.child_type;
+    }
+    return false;
+}
+
 static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const Decl *decl,
     HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> *type_table)
 {
@@ -243,7 +256,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
                 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
                 switch (builtin_ty->getKind()) {
                     case BuiltinType::Void:
-                        return c->codegen->builtin_types.entry_void;
+                        return get_c_void_type(c);
                     case BuiltinType::Bool:
                         return c->codegen->builtin_types.entry_bool;
                     case BuiltinType::Char_U:
@@ -273,6 +286,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
                     case BuiltinType::Double:
                         return c->codegen->builtin_types.entry_f64;
                     case BuiltinType::LongDouble:
+                        return c->codegen->builtin_types.entry_c_long_double;
                     case BuiltinType::WChar_U:
                     case BuiltinType::Char16:
                     case BuiltinType::Char32:
@@ -322,10 +336,6 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
                 }
                 bool is_const = child_qt.isConstQualified();
 
-                if (child_type->id == TypeTableEntryIdVoid) {
-                    child_type = get_c_void_type(c);
-                }
-
                 TypeTableEntry *non_null_pointer_type = get_pointer_to_type(c->codegen, child_type, is_const);
                 return get_maybe_type(c->codegen, non_null_pointer_type);
             }
@@ -421,8 +431,13 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
                 } else {
                     fn_type_id.return_type = resolve_qual_type(c, fn_proto_ty->getReturnType(), decl);
                     if (get_underlying_type(fn_type_id.return_type)->id == TypeTableEntryIdInvalid) {
+                        emit_warning(c, decl, "unresolved function proto return type");
                         return c->codegen->builtin_types.entry_invalid;
                     }
+                    // convert c_void to actual void (only for return type)
+                    if (is_c_void_type(c, fn_type_id.return_type)) {
+                        fn_type_id.return_type = c->codegen->builtin_types.entry_void;
+                    }
                 }
 
                 fn_type_id.param_info = allocate<FnTypeParamInfo>(fn_type_id.param_count);
@@ -431,6 +446,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
                     TypeTableEntry *param_type = resolve_qual_type(c, qt, decl);
 
                     if (get_underlying_type(param_type)->id == TypeTableEntryIdInvalid) {
+                        emit_warning(c, decl, "unresolved function proto parameter type");
                         return c->codegen->builtin_types.entry_invalid;
                     }
 
@@ -466,6 +482,10 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
             {
                 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
                 TypeTableEntry *child_type = resolve_qual_type(c, const_arr_ty->getElementType(), decl);
+                if (child_type->id == TypeTableEntryIdInvalid) {
+                    emit_warning(c, decl, "unresolved array element type");
+                    return child_type;
+                }
                 uint64_t size = const_arr_ty->getSize().getLimitedValue();
                 return get_array_type(c->codegen, child_type, size);
             }
@@ -601,6 +621,10 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
     // TODO
 
     TypeTableEntry *child_type = resolve_qual_type(c, child_qt, typedef_decl);
+    if (child_type->id == TypeTableEntryIdInvalid) {
+        emit_warning(c, typedef_decl, "typedef %s - unresolved child type", buf_ptr(type_name));
+        return;
+    }
     TypeTableEntry *decl_type = get_typedecl_type(c->codegen, buf_ptr(type_name), child_type);
     add_typedef_node(c, decl_type);
 }
test/run_tests.cpp
@@ -1903,9 +1903,10 @@ int foo(char a, unsigned char b, signed char c);
 int foo(char a, unsigned char b, signed char c); // test a duplicate prototype
 void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
 void baz(int8_t a, int16_t b, int32_t c, int64_t d);
-    )SOURCE", 1, R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;
-pub extern fn bar(a: u8, b: u16, c: u32, d: u64);
-pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT");
+    )SOURCE", 3,
+            "pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;",
+            "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);",
+            "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);");
 
     add_parseh_case("noreturn attribute", R"SOURCE(
 void foo(void) __attribute__((noreturn));
@@ -1953,7 +1954,7 @@ enum Bar {
     BarB,
 };
 void func(struct Foo *a, enum Bar **b);
-    )SOURCE", 2, R"OUTPUT(export struct struct_Foo {
+    )SOURCE", 3, R"OUTPUT(export struct struct_Foo {
     x: c_int,
     y: c_int,
 }
@@ -1962,8 +1963,8 @@ export enum enum_Bar {
     B,
 }
 pub const BarA = enum_Bar.A;
-pub const BarB = enum_Bar.B;
-pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT",
+pub const BarB = enum_Bar.B;)OUTPUT",
+            "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);",
     R"OUTPUT(pub const Foo = struct_Foo;
 pub const Bar = enum_Bar;)OUTPUT");
 
@@ -2038,6 +2039,15 @@ struct Bar {
             R"SOURCE(export struct struct_Foo {
     next: ?&struct_Bar,
 })SOURCE");
+
+
+    add_parseh_case("typedef void", R"SOURCE(
+typedef void Foo;
+Foo fun(Foo *a);
+    )SOURCE", 3,
+            "pub type c_void = u8;",
+            "pub type Foo = c_void;",
+            "pub extern fn fun(a: ?&Foo);");
 }
 
 static void print_compiler_invocation(TestCase *test_case) {