authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-24 19:26:05-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-24 19:26:05-05:00
log40480c7cdc84697219e8b2434772709ad948ed4d
tree6ed2ee9b52fad5cff463ca6e944d897884ae3b93
parent68312afcdf5a75ddc95dc21cb2f610780c0b69a6

translate-c supports string literals


2 files changed, 79 insertions(+), 6 deletions(-)

src/translate_c.cpp+69-6
......@@ -324,6 +324,10 @@ static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
324324 return node;
325325}
326326
327static Buf *string_ref_to_buf(StringRef string_ref) {
328 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
329}
330
327331static const char *decl_name(const Decl *decl) {
328332 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
329333 return (const char *)named_decl->getName().bytes_begin();
......@@ -339,6 +343,44 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
339343
340344static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
341345
346static QualType get_expr_qual_type(Context *c, const Expr *expr) {
347 // String literals in C are `char *` but they should really be `const char *`.
348 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
349 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
350 if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {
351 const Expr *sub_expr = cast_expr->getSubExpr();
352 if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {
353 QualType array_qt = sub_expr->getType();
354 const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr());
355 QualType pointee_qt = array_type->getElementType();
356 pointee_qt.addConst();
357 return c->ctx->getPointerType(pointee_qt);
358 }
359 }
360 }
361 return expr->getType();
362}
363
364static AstNode *get_expr_type(Context *c, const Expr *expr) {
365 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
366}
367
368static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {
369 QualType t1 = get_expr_qual_type(c, expr1);
370 QualType t2 = get_expr_qual_type(c, expr2);
371
372 if (t1.isConstQualified() != t2.isConstQualified()) {
373 return false;
374 }
375 if (t1.isVolatileQualified() != t2.isVolatileQualified()) {
376 return false;
377 }
378 if (t1.isRestrictQualified() != t2.isRestrictQualified()) {
379 return false;
380 }
381 return t1.getTypePtr() == t2.getTypePtr();
382}
383
342384static bool is_c_void_type(AstNode *node) {
343385 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
344386}
......@@ -1335,7 +1377,11 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas
13351377 if (target_node == nullptr)
13361378 return nullptr;
13371379
1338 AstNode *dest_type_node = trans_qual_type(c, stmt->getType(), stmt->getLocStart());
1380 if (expr_types_equal(c, stmt, stmt->getSubExpr())) {
1381 return target_node;
1382 }
1383
1384 AstNode *dest_type_node = get_expr_type(c, stmt);
13391385
13401386 AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
13411387 node->data.fn_call_expr.params.append(dest_type_node);
......@@ -2126,6 +2172,24 @@ static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) {
21262172 return while_node;
21272173}
21282174
2175static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral *stmt) {
2176 switch (stmt->getKind()) {
2177 case StringLiteral::Ascii:
2178 case StringLiteral::UTF8:
2179 return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
2180 case StringLiteral::UTF16:
2181 emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");
2182 return nullptr;
2183 case StringLiteral::UTF32:
2184 emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");
2185 return nullptr;
2186 case StringLiteral::Wide:
2187 emit_warning(c, stmt->getLocStart(), "TODO support wide string literals");
2188 return nullptr;
2189 }
2190 zig_unreachable();
2191}
2192
21292193static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {
21302194 Stmt::StmtClass sc = stmt->getStmtClass();
21312195 switch (sc) {
......@@ -2167,6 +2231,8 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
21672231 return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt);
21682232 case Stmt::DoStmtClass:
21692233 return trans_do_loop(c, block, (DoStmt *)stmt);
2234 case Stmt::StringLiteralClass:
2235 return trans_string_literal(c, block, (StringLiteral *)stmt);
21702236 case Stmt::CaseStmtClass:
21712237 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");
21722238 return nullptr;
......@@ -2488,9 +2554,6 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
24882554 case Stmt::StmtExprClass:
24892555 emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
24902556 return nullptr;
2491 case Stmt::StringLiteralClass:
2492 emit_warning(c, stmt->getLocStart(), "TODO handle C StringLiteralClass");
2493 return nullptr;
24942557 case Stmt::SubstNonTypeTemplateParmExprClass:
24952558 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
24962559 return nullptr;
......@@ -3530,7 +3593,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
35303593 break;
35313594 }
35323595 StringRef msg_str_ref = it->getMessage();
3533 Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin());
3596 Buf *msg = string_ref_to_buf(msg_str_ref);
35343597 FullSourceLoc fsl = it->getLocation();
35353598 if (fsl.hasManager()) {
35363599 FileID file_id = fsl.getFileID();
......@@ -3543,7 +3606,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
35433606 if (filename.empty()) {
35443607 path = buf_alloc();
35453608 } else {
3546 path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size());
3609 path = string_ref_to_buf(filename);
35473610 }
35483611
35493612 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
test/translate_c.zig+10
......@@ -929,6 +929,16 @@ pub fn addCases(cases: &tests.TranslateCContext) {
929929 \\ return *(??ptr);
930930 \\}
931931 );
932
933 cases.add("string literal",
934 \\const char *foo(void) {
935 \\ return "bar";
936 \\}
937 ,
938 \\pub fn foo() -> ?&const u8 {
939 \\ return c"bar";
940 \\}
941 );
932942}
933943
934944