diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 3295560af3..f5c1ef5810 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -28,36 +28,6 @@ struct Alias { Buf *canon_name; }; -struct Context { - ImportTableEntry *import; - ZigList *errors; - VisibMod visib_mod; - VisibMod export_visib_mod; - AstNode *root; - HashMap decl_table; - HashMap macro_table; - HashMap global_table; - SourceManager *source_manager; - ZigList aliases; - AstNode *source_node; - bool warnings_on; - - CodeGen *codegen; - ASTContext *ctx; - - HashMap ptr_params; -}; - -enum ResultUsed { - ResultUsedNo, - ResultUsedYes, -}; - -enum TransLRValue { - TransLValue, - TransRValue, -}; - enum TransScopeId { TransScopeIdSwitch, TransScopeIdVar, @@ -99,6 +69,37 @@ struct TransScopeWhile { AstNode *node; }; +struct Context { + ImportTableEntry *import; + ZigList *errors; + VisibMod visib_mod; + VisibMod export_visib_mod; + AstNode *root; + HashMap decl_table; + HashMap macro_table; + HashMap global_table; + SourceManager *source_manager; + ZigList aliases; + AstNode *source_node; + bool warnings_on; + + CodeGen *codegen; + ASTContext *ctx; + + TransScopeRoot *global_scope; + HashMap ptr_params; +}; + +enum ResultUsed { + ResultUsedNo, + ResultUsedYes, +}; + +enum TransLRValue { + TransLValue, + TransRValue, +}; + static TransScopeRoot *trans_scope_root_create(Context *c); static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope); static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope); @@ -3233,8 +3234,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { return; } - TransScopeRoot *root_scope = trans_scope_root_create(c); - TransScope *scope = &root_scope->base; + TransScope *scope = &c->global_scope->base; for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { AstNode *param_node = proto_node->data.fn_proto.params.at(i); @@ -3600,6 +3600,93 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { } } +static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) { + switch (ap_value->getKind()) { + case APValue::Int: + return trans_create_node_apint(c, ap_value->getInt()); + case APValue::Uninitialized: + return trans_create_node(c, NodeTypeUndefinedLiteral); + case APValue::Array: { + emit_warning(c, source_loc, "TODO add a test case for this code"); + + unsigned init_count = ap_value->getArrayInitializedElts(); + unsigned all_count = ap_value->getArraySize(); + unsigned leftover_count = all_count - init_count; + AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr); + AstNode *arr_type_node = trans_qual_type(c, qt, source_loc); + init_node->data.container_init_expr.type = arr_type_node; + init_node->data.container_init_expr.kind = ContainerInitKindArray; + + QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType(); + + for (size_t i = 0; i < init_count; i += 1) { + APValue &elem_ap_val = ap_value->getArrayInitializedElt(i); + AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc); + if (elem_node == nullptr) + return nullptr; + init_node->data.container_init_expr.entries.append(elem_node); + } + if (leftover_count == 0) { + return init_node; + } + + APValue &filler_ap_val = ap_value->getArrayFiller(); + AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc); + if (filler_node == nullptr) + return nullptr; + + AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr); + init_node->data.container_init_expr.type = arr_type_node; + init_node->data.container_init_expr.kind = ContainerInitKindArray; + init_node->data.container_init_expr.entries.append(filler_node); + + AstNode *rhs_node; + if (leftover_count == 1) { + rhs_node = filler_arr_1; + } else { + AstNode *amt_node = trans_create_node_unsigned(c, leftover_count); + rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node); + } + + return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node); + } + case APValue::LValue: { + const APValue::LValueBase lval_base = ap_value->getLValueBase(); + if (const Expr *expr = lval_base.dyn_cast()) { + return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue); + } + //const ValueDecl *value_decl = lval_base.get(); + emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl"); + return nullptr; + } + case APValue::Float: + emit_warning(c, source_loc, "unsupported initializer value kind: Float"); + return nullptr; + case APValue::ComplexInt: + emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt"); + return nullptr; + case APValue::ComplexFloat: + emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat"); + return nullptr; + case APValue::Vector: + emit_warning(c, source_loc, "unsupported initializer value kind: Vector"); + return nullptr; + case APValue::Struct: + emit_warning(c, source_loc, "unsupported initializer value kind: Struct"); + return nullptr; + case APValue::Union: + emit_warning(c, source_loc, "unsupported initializer value kind: Union"); + return nullptr; + case APValue::MemberPointer: + emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer"); + return nullptr; + case APValue::AddrLabelDiff: + emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff"); + return nullptr; + } + zig_unreachable(); +} + static void visit_var_decl(Context *c, const VarDecl *var_decl) { Buf *name = buf_create_from_str(decl_name(var_decl)); @@ -3636,27 +3723,9 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) { "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); return; } - switch (ap_value->getKind()) { - case APValue::Int: - init_node = trans_create_node_apint(c, ap_value->getInt()); - break; - case APValue::Uninitialized: - init_node = trans_create_node(c, NodeTypeUndefinedLiteral); - break; - case APValue::Float: - case APValue::ComplexInt: - case APValue::ComplexFloat: - case APValue::LValue: - case APValue::Vector: - case APValue::Array: - case APValue::Struct: - case APValue::Union: - case APValue::MemberPointer: - case APValue::AddrLabelDiff: - emit_warning(c, var_decl->getLocation(), - "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name)); - return; - } + init_node = trans_ap_value(c, ap_value, qt, var_decl->getLocation()); + if (init_node == nullptr) + return; } else { init_node = trans_create_node(c, NodeTypeUndefinedLiteral); } @@ -4101,6 +4170,7 @@ int parse_h_file(ImportTableEntry *import, ZigList *errors, const ch c->ptr_params.init(8); c->codegen = codegen; c->source_node = source_node; + c->global_scope = trans_scope_root_create(c); ZigList clang_argv = {0}; diff --git a/test/translate_c.zig b/test/translate_c.zig index 8a8d1d334b..90b99b5faf 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1172,4 +1172,10 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return u32_0; \\} ); + + cases.add("const ptr initializer", + \\static const char *v0 = "0.0.0"; + , + \\pub var v0: ?&const u8 = c"0.0.0"; + ); }