Commit cc621cdee3

Andrew Kelley <superjoe30@gmail.com>
2017-09-05 06:21:02
fix parseh bugs
1 parent e1d5da2
src/ast_render.cpp
@@ -412,14 +412,17 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
                 const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);
                 const char *extern_str = extern_string(node->data.fn_proto.is_extern);
                 const char *inline_str = inline_string(node->data.fn_proto.is_inline);
-                fprintf(ar->f, "%s%s%sfn ", pub_str, inline_str, extern_str);
-                print_symbol(ar, node->data.fn_proto.name);
+                fprintf(ar->f, "%s%s%sfn", pub_str, inline_str, extern_str);
+                if (node->data.fn_proto.name != nullptr) {
+                    fprintf(ar->f, " ");
+                    print_symbol(ar, node->data.fn_proto.name);
+                }
                 fprintf(ar->f, "(");
                 size_t arg_count = node->data.fn_proto.params.length;
                 for (size_t arg_i = 0; arg_i < arg_count; arg_i += 1) {
                     AstNode *param_decl = node->data.fn_proto.params.at(arg_i);
                     assert(param_decl->type == NodeTypeParamDecl);
-                    if (buf_len(param_decl->data.param_decl.name) > 0) {
+                    if (param_decl->data.param_decl.name != nullptr) {
                         const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
                         const char *inline_str = param_decl->data.param_decl.is_inline ? "inline " : "";
                         fprintf(ar->f, "%s%s", noalias_str, inline_str);
src/errmsg.cpp
@@ -79,11 +79,14 @@ ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size
     for (;;) {
         if (line_start_offset == 0) {
             break;
-        } else if (source[line_start_offset] == '\n') {
+        }
+
+        line_start_offset -= 1;
+
+        if (source[line_start_offset] == '\n') {
             line_start_offset += 1;
             break;
         }
-        line_start_offset -= 1;
     }
 
     size_t line_end_offset = offset;
src/parseh.cpp
@@ -30,8 +30,8 @@ struct MacroSymbol {
 };
 
 struct Alias {
-    Buf *name;
-    AstNode *node;
+    Buf *new_name;
+    Buf *canon_name;
 };
 
 struct Context {
@@ -85,10 +85,10 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
     fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
 }
 
-static void add_global_weak_alias(Context *c, Buf *name, AstNode *node) {
+static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) {
     Alias *alias = c->aliases.add_one();
-    alias->name = name;
-    alias->node = node;
+    alias->new_name = new_name;
+    alias->canon_name = canon_name;
 }
 
 static AstNode * trans_create_node(Context *c, NodeType id) {
@@ -128,7 +128,7 @@ static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *na
 }
 
 static AstNode *trans_create_node_opaque(Context *c) {
-    return trans_create_node_builtin_fn_call_str(c, "opaque");
+    return trans_create_node_builtin_fn_call_str(c, "OpaqueType");
 }
 
 static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
@@ -209,7 +209,7 @@ static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_n
 static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) {
     AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
     AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
-    fn_proto->data.fn_proto.visib_mod = c->visib_mod;;
+    fn_proto->data.fn_proto.visib_mod = c->visib_mod;
     fn_proto->data.fn_proto.name = fn_name;
     fn_proto->data.fn_proto.is_inline = true;
     fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
@@ -559,6 +559,7 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo
                 switch (fn_proto_ty->getCallConv()) {
                     case CC_C:           // __attribute__((cdecl))
                         proto_node->data.fn_proto.cc = CallingConventionC;
+                        proto_node->data.fn_proto.is_extern = true;
                         break;
                     case CC_X86StdCall:  // __attribute__((stdcall))
                         proto_node->data.fn_proto.cc = CallingConventionStdcall;
@@ -646,9 +647,7 @@ static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLo
                     AstNode *param_node = trans_create_node(c, NodeTypeParamDecl);
                     //emit_warning(c, source_loc, "TODO figure out fn prototype param name");
                     const char *param_name = nullptr;
-                    if (param_name == nullptr) {
-                        param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
-                    } else {
+                    if (param_name != nullptr) {
                         param_node->data.param_decl.name = buf_create_from_str(param_name);
                     }
                     param_node->data.param_decl.is_noalias = qt.isRestrictQualified();
@@ -1662,7 +1661,14 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
         AstNode *param_node = proto_node->data.fn_proto.params.at(i);
         const ParmVarDecl *param = fn_decl->getParamDecl(i);
         const char *name = decl_name(param);
-        if (strlen(name) != 0) {
+        if (strlen(name) == 0) {
+            Buf *proto_param_name = param_node->data.param_decl.name;
+            if (proto_param_name == nullptr) {
+                param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
+            } else {
+                param_node->data.param_decl.name = proto_param_name;
+            }
+        } else {
             param_node->data.param_decl.name = buf_create_from_str(name);
         }
     }
@@ -1714,6 +1720,22 @@ static void visit_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl)
     c->global_type_table.put(type_name, type_node);
 }
 
+struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
+        Buf *full_type_name, Buf *bare_name)
+{
+    AstNode *opaque_node = trans_create_node_opaque(c);
+    if (full_type_name == nullptr) {
+        c->decl_table.put(enum_decl, opaque_node);
+        return opaque_node;
+    }
+    AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
+    c->enum_type_table.put(bare_name, symbol_node);
+    add_global_weak_alias(c, bare_name, full_type_name);
+    add_global_var(c, full_type_name, opaque_node);
+    c->decl_table.put(enum_decl, symbol_node);
+    return symbol_node;
+}
+
 static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
     auto existing_entry = c->decl_table.maybe_get((void*)enum_decl);
     if (existing_entry) {
@@ -1727,14 +1749,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
 
     const EnumDecl *enum_def = enum_decl->getDefinition();
     if (!enum_def) {
-        AstNode *opaque_node = trans_create_node_opaque(c);
-        if (!is_anonymous) {
-            c->enum_type_table.put(bare_name, opaque_node);
-            add_global_weak_alias(c, bare_name, opaque_node);
-            add_global_var(c, full_type_name, opaque_node);
-        }
-        c->decl_table.put(enum_decl, opaque_node);
-        return opaque_node;
+        return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
     }
 
     bool pure_enum = true;
@@ -1786,14 +1801,17 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
             add_global_var(c, enum_val_name, field_access_node);
         }
 
-        if (!is_anonymous) {
-            c->enum_type_table.put(bare_name, enum_node);
-            add_global_weak_alias(c, bare_name, enum_node);
+        if (is_anonymous) {
+            c->decl_table.put(enum_decl, enum_node);
+            return enum_node;
+        } else {
+            AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
+            c->enum_type_table.put(bare_name, symbol_node);
+            add_global_weak_alias(c, bare_name, full_type_name);
             add_global_var(c, full_type_name, enum_node);
+            c->decl_table.put(enum_decl, symbol_node);
+            return enum_node;
         }
-        c->decl_table.put(enum_decl, enum_node);
-
-        return enum_node;
     }
 
     // TODO after issue #305 is solved, make this be an enum with tag_int_type
@@ -1814,14 +1832,32 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
         var_node->data.variable_declaration.type = tag_int_type;
     }
 
-    if (!is_anonymous) {
-        c->enum_type_table.put(bare_name, enum_node);
-        add_global_weak_alias(c, bare_name, enum_node);
+    if (is_anonymous) {
+        c->decl_table.put(enum_decl, enum_node);
+        return enum_node;
+    } else {
+        AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
+        c->enum_type_table.put(bare_name, symbol_node);
+        add_global_weak_alias(c, bare_name, full_type_name);
         add_global_var(c, full_type_name, enum_node);
+        return symbol_node;
     }
-    c->decl_table.put(enum_decl, enum_node);
+}
 
-    return enum_node;
+static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,
+        Buf *full_type_name, Buf *bare_name)
+{
+    AstNode *opaque_node = trans_create_node_opaque(c);
+    if (full_type_name == nullptr) {
+        c->decl_table.put(record_decl, opaque_node);
+        return opaque_node;
+    }
+    AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
+    c->struct_type_table.put(bare_name, symbol_node);
+    add_global_weak_alias(c, bare_name, full_type_name);
+    add_global_var(c, full_type_name, opaque_node);
+    c->decl_table.put(record_decl, symbol_node);
+    return symbol_node;
 }
 
 static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
@@ -1834,7 +1870,6 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
 
     if (!record_decl->isStruct()) {
         emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct", raw_name);
-        c->decl_table.put(record_decl, nullptr);
         return nullptr;
     }
 
@@ -1844,14 +1879,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
 
     RecordDecl *record_def = record_decl->getDefinition();
     if (record_def == nullptr) {
-        AstNode *opaque_node = trans_create_node_opaque(c);
-        if (!is_anonymous) {
-            c->struct_type_table.put(bare_name, opaque_node);
-            add_global_weak_alias(c, bare_name, opaque_node);
-            add_global_var(c, full_type_name, opaque_node);
-        }
-        c->decl_table.put(record_decl, opaque_node);
-        return opaque_node;
+        return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
     }
 
     // count fields and validate
@@ -1865,16 +1893,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
         if (field_decl->isBitField()) {
             emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield",
                     is_anonymous ? "(anon)" : buf_ptr(bare_name));
-
-            AstNode *opaque_node = trans_create_node_opaque(c);
-
-            if (!is_anonymous) {
-                c->struct_type_table.put(bare_name, opaque_node);
-                add_global_weak_alias(c, bare_name, opaque_node);
-                add_global_var(c, full_type_name, opaque_node);
-            }
-            c->decl_table.put(record_decl, opaque_node);
-            return opaque_node;;
+            return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
         }
     }
 
@@ -1887,12 +1906,14 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
     struct_node->data.container_decl.fields.resize(field_count);
 
     // must be before fields in case a circular reference happens
-    if (!is_anonymous) {
+    if (is_anonymous) {
+        c->decl_table.put(record_decl, struct_node);
+    } else {
         c->struct_type_table.put(bare_name, struct_node);
-        add_global_weak_alias(c, bare_name, struct_node);
+        add_global_weak_alias(c, bare_name, full_type_name);
         add_global_var(c, full_type_name, struct_node);
+        c->decl_table.put(record_decl, trans_create_node_symbol(c, full_type_name));
     }
-    c->decl_table.put(record_decl, struct_node);
 
     uint32_t i = 0;
     for (auto it = record_def->field_begin(),
@@ -1910,22 +1931,17 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
                     "struct %s demoted to opaque type - unresolved type",
                     is_anonymous ? "(anon)" : buf_ptr(bare_name));
 
-            AstNode *opaque_node = trans_create_node_opaque(c);
-            if (!is_anonymous) {
-                c->struct_type_table.put(bare_name, opaque_node);
-                add_global_weak_alias(c, bare_name, opaque_node);
-                add_global_var(c, full_type_name, opaque_node);
-            }
-            c->decl_table.put(record_decl, opaque_node);
-
-            return opaque_node;
+            return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
         }
 
         struct_node->data.container_decl.fields.items[i] = field_node;
     }
 
-
-    return struct_node;
+    if (is_anonymous) {
+        return struct_node;
+    } else {
+        return trans_create_node_symbol(c, full_type_name);
+    }
 }
 
 static void visit_var_decl(Context *c, const VarDecl *var_decl) {
@@ -2045,10 +2061,10 @@ static bool name_exists(Context *c, Buf *name) {
 static void render_aliases(Context *c) {
     for (size_t i = 0; i < c->aliases.length; i += 1) {
         Alias *alias = &c->aliases.at(i);
-        if (name_exists(c, alias->name))
+        if (name_exists(c, alias->new_name))
             continue;
 
-        add_global_var(c, alias->name, alias->node);
+        add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name));
     }
 }
 
@@ -2174,7 +2190,7 @@ static void process_symbol_macros(Context *c) {
             }
         }
 
-        add_global_var(c, ms.name, existing_node);
+        add_global_var(c, ms.name, trans_create_node_symbol(c, ms.value));
     }
 }
 
src/parser.cpp
@@ -22,7 +22,6 @@ struct ParseContext {
     ErrColor err_color;
     // These buffers are used freqently so we preallocate them once here.
     Buf *void_buf;
-    Buf *empty_buf;
 };
 
 __attribute__ ((format (printf, 4, 5)))
@@ -276,7 +275,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, size_t *token_index) {
         token = &pc->tokens->at(*token_index);
     }
 
-    node->data.param_decl.name = pc->empty_buf;
+    node->data.param_decl.name = nullptr;
 
     if (token->id == TokenIdSymbol) {
         Token *next_token = &pc->tokens->at(*token_index + 1);
@@ -2246,7 +2245,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
         *token_index += 1;
         node->data.fn_proto.name = token_buf(fn_name);
     } else {
-        node->data.fn_proto.name = pc->empty_buf;
+        node->data.fn_proto.name = nullptr;
     }
 
     ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);
@@ -2612,7 +2611,6 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner,
 {
     ParseContext pc = {0};
     pc.void_buf = buf_create_from_str("void");
-    pc.empty_buf = buf_create_from_str("");
     pc.err_color = err_color;
     pc.owner = owner;
     pc.buf = buf;
test/parseh.zig
@@ -44,11 +44,11 @@ pub fn addCases(cases: &tests.ParseHContext) {
         \\    @"1",
         \\};
     ,
-        \\pub const FooA = Foo.A;
+        \\pub const FooA = enum_Foo.A;
     ,
-        \\pub const FooB = Foo.B;
+        \\pub const FooB = enum_Foo.B;
     ,
-        \\pub const Foo1 = Foo.1;
+        \\pub const Foo1 = enum_Foo.@"1";
     ,
         \\pub const Foo = enum_Foo;
     );
@@ -94,9 +94,9 @@ pub fn addCases(cases: &tests.ParseHContext) {
         \\    B,
         \\};
     ,
-        \\pub const BarA = 0;
+        \\pub const BarA = enum_Bar.A;
     ,
-        \\pub const BarB = 1;
+        \\pub const BarB = enum_Bar.B;
     ,
         \\pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);
     ,