Commit 40480c7cdc
Changed files (2)
test
src/translate_c.cpp
@@ -324,6 +324,10 @@ static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
return node;
}
+static Buf *string_ref_to_buf(StringRef string_ref) {
+ return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
+}
+
static const char *decl_name(const Decl *decl) {
const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
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)
static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
+static QualType get_expr_qual_type(Context *c, const Expr *expr) {
+ // String literals in C are `char *` but they should really be `const char *`.
+ if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
+ const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
+ if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {
+ const Expr *sub_expr = cast_expr->getSubExpr();
+ if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {
+ QualType array_qt = sub_expr->getType();
+ const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr());
+ QualType pointee_qt = array_type->getElementType();
+ pointee_qt.addConst();
+ return c->ctx->getPointerType(pointee_qt);
+ }
+ }
+ }
+ return expr->getType();
+}
+
+static AstNode *get_expr_type(Context *c, const Expr *expr) {
+ return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
+}
+
+static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {
+ QualType t1 = get_expr_qual_type(c, expr1);
+ QualType t2 = get_expr_qual_type(c, expr2);
+
+ if (t1.isConstQualified() != t2.isConstQualified()) {
+ return false;
+ }
+ if (t1.isVolatileQualified() != t2.isVolatileQualified()) {
+ return false;
+ }
+ if (t1.isRestrictQualified() != t2.isRestrictQualified()) {
+ return false;
+ }
+ return t1.getTypePtr() == t2.getTypePtr();
+}
+
static bool is_c_void_type(AstNode *node) {
return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
}
@@ -1335,7 +1377,11 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas
if (target_node == nullptr)
return nullptr;
- AstNode *dest_type_node = trans_qual_type(c, stmt->getType(), stmt->getLocStart());
+ if (expr_types_equal(c, stmt, stmt->getSubExpr())) {
+ return target_node;
+ }
+
+ AstNode *dest_type_node = get_expr_type(c, stmt);
AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
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) {
return while_node;
}
+static AstNode *trans_string_literal(Context *c, AstNode *block, StringLiteral *stmt) {
+ switch (stmt->getKind()) {
+ case StringLiteral::Ascii:
+ case StringLiteral::UTF8:
+ return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
+ case StringLiteral::UTF16:
+ emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");
+ return nullptr;
+ case StringLiteral::UTF32:
+ emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");
+ return nullptr;
+ case StringLiteral::Wide:
+ emit_warning(c, stmt->getLocStart(), "TODO support wide string literals");
+ return nullptr;
+ }
+ zig_unreachable();
+}
+
static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {
Stmt::StmtClass sc = stmt->getStmtClass();
switch (sc) {
@@ -2167,6 +2231,8 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt);
case Stmt::DoStmtClass:
return trans_do_loop(c, block, (DoStmt *)stmt);
+ case Stmt::StringLiteralClass:
+ return trans_string_literal(c, block, (StringLiteral *)stmt);
case Stmt::CaseStmtClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");
return nullptr;
@@ -2488,9 +2554,6 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
case Stmt::StmtExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
return nullptr;
- case Stmt::StringLiteralClass:
- emit_warning(c, stmt->getLocStart(), "TODO handle C StringLiteralClass");
- return nullptr;
case Stmt::SubstNonTypeTemplateParmExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
return nullptr;
@@ -3530,7 +3593,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
break;
}
StringRef msg_str_ref = it->getMessage();
- Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin());
+ Buf *msg = string_ref_to_buf(msg_str_ref);
FullSourceLoc fsl = it->getLocation();
if (fsl.hasManager()) {
FileID file_id = fsl.getFileID();
@@ -3543,7 +3606,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
if (filename.empty()) {
path = buf_alloc();
} else {
- path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size());
+ path = string_ref_to_buf(filename);
}
ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
test/translate_c.zig
@@ -929,6 +929,16 @@ pub fn addCases(cases: &tests.TranslateCContext) {
\\ return *(??ptr);
\\}
);
+
+ cases.add("string literal",
+ \\const char *foo(void) {
+ \\ return "bar";
+ \\}
+ ,
+ \\pub fn foo() -> ?&const u8 {
+ \\ return c"bar";
+ \\}
+ );
}