Merge pull request #2069 from ziglang/glibc-assert-translation
Implemented enough of translate-c to translate assert
This commit is contained in:
commit
a17bf219c6
@ -690,6 +690,13 @@ static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
|
||||
static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
|
||||
clang::QualType src_type, AstNode *expr)
|
||||
{
|
||||
// The only way void pointer casts are valid C code, is if
|
||||
// the value of the expression is ignored. We therefore just
|
||||
// return the expr, and let the system that ignores values
|
||||
// translate this correctly.
|
||||
if (qual_type_canon(dest_type)->isVoidType()) {
|
||||
return expr;
|
||||
}
|
||||
if (qual_types_equal(dest_type, src_type)) {
|
||||
return expr;
|
||||
}
|
||||
@ -1225,6 +1232,31 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::
|
||||
return child_scope_block->node;
|
||||
}
|
||||
|
||||
static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, TransScope *scope,
|
||||
const clang::StmtExpr *stmt, TransScope **out_node_scope)
|
||||
{
|
||||
AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope);
|
||||
if (block == nullptr)
|
||||
return block;
|
||||
assert(block->type == NodeTypeBlock);
|
||||
if (block->data.block.statements.length == 0)
|
||||
return block;
|
||||
|
||||
Buf *label = buf_create_from_str("x");
|
||||
block->data.block.name = label;
|
||||
AstNode *return_expr = block->data.block.statements.pop();
|
||||
if (return_expr->type == NodeTypeBinOpExpr &&
|
||||
return_expr->data.bin_op_expr.bin_op == BinOpTypeAssign &&
|
||||
return_expr->data.bin_op_expr.op1->type == NodeTypeSymbol)
|
||||
{
|
||||
Buf *symbol_buf = return_expr->data.bin_op_expr.op1->data.symbol_expr.symbol;
|
||||
if (strcmp("_", buf_ptr(symbol_buf)) == 0)
|
||||
return_expr = return_expr->data.bin_op_expr.op2;
|
||||
}
|
||||
block->data.block.statements.append(trans_create_node_break(c, label, return_expr));
|
||||
return maybe_suppress_result(c, result_used, block);
|
||||
}
|
||||
|
||||
static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
|
||||
const clang::Expr *value_expr = stmt->getRetValue();
|
||||
if (value_expr == nullptr) {
|
||||
@ -1238,13 +1270,15 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re
|
||||
}
|
||||
}
|
||||
|
||||
static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
|
||||
static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) {
|
||||
llvm::APSInt result;
|
||||
if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
|
||||
emit_warning(c, stmt->getLocStart(), "invalid integer literal");
|
||||
return nullptr;
|
||||
}
|
||||
return trans_create_node_apint(c, result);
|
||||
|
||||
AstNode *node = trans_create_node_apint(c, result);
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
|
||||
static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
|
||||
@ -1381,14 +1415,17 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
|
||||
case clang::BO_Cmp:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_Cmp");
|
||||
return nullptr;
|
||||
case clang::BO_Mul:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(),
|
||||
case clang::BO_Mul: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),
|
||||
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
|
||||
stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Div:
|
||||
if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
|
||||
// unsigned/float division uses the operator
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
} else {
|
||||
// signed integer division uses @divTrunc
|
||||
AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
|
||||
@ -1398,12 +1435,13 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
|
||||
AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue);
|
||||
if (rhs == nullptr) return nullptr;
|
||||
fn_call->data.fn_call_expr.params.append(rhs);
|
||||
return fn_call;
|
||||
return maybe_suppress_result(c, result_used, fn_call);
|
||||
}
|
||||
case clang::BO_Rem:
|
||||
if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
|
||||
// unsigned/float division uses the operator
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
} else {
|
||||
// signed integer division uses @rem
|
||||
AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
|
||||
@ -1413,42 +1451,72 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
|
||||
AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue);
|
||||
if (rhs == nullptr) return nullptr;
|
||||
fn_call->data.fn_call_expr.params.append(rhs);
|
||||
return fn_call;
|
||||
return maybe_suppress_result(c, result_used, fn_call);
|
||||
}
|
||||
case clang::BO_Add:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(),
|
||||
case clang::BO_Add: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),
|
||||
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
|
||||
stmt->getRHS());
|
||||
case clang::BO_Sub:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(),
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Sub: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(),
|
||||
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
|
||||
stmt->getRHS());
|
||||
case clang::BO_Shl:
|
||||
return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
|
||||
case clang::BO_Shr:
|
||||
return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
|
||||
case clang::BO_LT:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
|
||||
case clang::BO_GT:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
|
||||
case clang::BO_LE:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
|
||||
case clang::BO_GE:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
|
||||
case clang::BO_EQ:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
|
||||
case clang::BO_NE:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
|
||||
case clang::BO_And:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
|
||||
case clang::BO_Xor:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
|
||||
case clang::BO_Or:
|
||||
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
|
||||
case clang::BO_LAnd:
|
||||
return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
|
||||
case clang::BO_LOr:
|
||||
return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Shl: {
|
||||
AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Shr: {
|
||||
AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_LT: {
|
||||
AstNode *node =trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_GT: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_LE: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_GE: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_EQ: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_NE: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_And: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Xor: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Or: {
|
||||
AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_LAnd: {
|
||||
AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_LOr: {
|
||||
AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::BO_Assign:
|
||||
return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
|
||||
case clang::BO_Comma:
|
||||
@ -1460,13 +1528,15 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
|
||||
AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue);
|
||||
if (lhs == nullptr)
|
||||
return nullptr;
|
||||
scope_block->node->data.block.statements.append(maybe_suppress_result(c, ResultUsedNo, lhs));
|
||||
scope_block->node->data.block.statements.append(lhs);
|
||||
|
||||
AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue);
|
||||
AstNode *rhs = trans_expr(c, ResultUsedYes, &scope_block->base, stmt->getRHS(), TransRValue);
|
||||
if (rhs == nullptr)
|
||||
return nullptr;
|
||||
scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
|
||||
return scope_block->node;
|
||||
|
||||
rhs = trans_create_node_break(c, label_name, rhs);
|
||||
scope_block->node->data.block.statements.append(rhs);
|
||||
return maybe_suppress_result(c, result_used, scope_block->node);
|
||||
}
|
||||
case clang::BO_MulAssign:
|
||||
case clang::BO_DivAssign:
|
||||
@ -1692,7 +1762,7 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
|
||||
static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
|
||||
switch (stmt->getCastKind()) {
|
||||
case clang::CK_LValueToRValue:
|
||||
return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
|
||||
@ -1701,8 +1771,9 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const cl
|
||||
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
|
||||
if (target_node == nullptr)
|
||||
return nullptr;
|
||||
return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
|
||||
AstNode *node = trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
|
||||
stmt->getSubExpr()->getType(), target_node);
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::CK_FunctionToPointerDecay:
|
||||
case clang::CK_ArrayToPointerDecay:
|
||||
@ -1710,7 +1781,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const cl
|
||||
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
|
||||
if (target_node == nullptr)
|
||||
return nullptr;
|
||||
return target_node;
|
||||
return maybe_suppress_result(c, result_used, target_node);
|
||||
}
|
||||
case clang::CK_BitCast:
|
||||
{
|
||||
@ -1727,7 +1798,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const cl
|
||||
AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
|
||||
node->data.fn_call_expr.params.append(dest_type_node);
|
||||
node->data.fn_call_expr.params.append(target_node);
|
||||
return node;
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::CK_NullToPointer:
|
||||
return trans_create_node_unsigned(c, 0);
|
||||
@ -2103,8 +2174,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag");
|
||||
return nullptr;
|
||||
case clang::UO_Extension:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension");
|
||||
return nullptr;
|
||||
return trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
|
||||
case clang::UO_Coawait:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait");
|
||||
return nullptr;
|
||||
@ -2721,7 +2791,9 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
|
||||
return node;
|
||||
}
|
||||
|
||||
static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) {
|
||||
static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope,
|
||||
const clang::MemberExpr *stmt)
|
||||
{
|
||||
AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
|
||||
if (container_node == nullptr)
|
||||
return nullptr;
|
||||
@ -2733,10 +2805,10 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::Me
|
||||
const char *name = decl_name(stmt->getMemberDecl());
|
||||
|
||||
AstNode *node = trans_create_node_field_access_str(c, container_node, name);
|
||||
return node;
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
|
||||
static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
|
||||
static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
|
||||
AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
|
||||
if (container_node == nullptr)
|
||||
return nullptr;
|
||||
@ -2749,21 +2821,25 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
|
||||
AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr);
|
||||
node->data.array_access_expr.array_ref_expr = container_node;
|
||||
node->data.array_access_expr.subscript = idx_node;
|
||||
return node;
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
|
||||
static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
|
||||
const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)
|
||||
{
|
||||
AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
|
||||
AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), lrvalue);
|
||||
if (sub_expr_node == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node);
|
||||
AstNode *cast = trans_c_cast(c, stmt->getLocStart(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node);
|
||||
if (cast == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return maybe_suppress_result(c, result_used, cast);
|
||||
}
|
||||
|
||||
static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
|
||||
const clang::UnaryExprOrTypeTraitExpr *stmt)
|
||||
static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used,
|
||||
TransScope *scope, const clang::UnaryExprOrTypeTraitExpr *stmt)
|
||||
{
|
||||
AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
|
||||
if (type_node == nullptr)
|
||||
@ -2771,7 +2847,7 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
|
||||
|
||||
AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf");
|
||||
node->data.fn_call_expr.params.append(type_node);
|
||||
return node;
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
|
||||
static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) {
|
||||
@ -3049,11 +3125,13 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const clan
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) {
|
||||
static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransScope *scope, const clang::StringLiteral *stmt) {
|
||||
switch (stmt->getKind()) {
|
||||
case clang::StringLiteral::Ascii:
|
||||
case clang::StringLiteral::UTF8:
|
||||
return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
|
||||
case clang::StringLiteral::UTF8: {
|
||||
AstNode *node = trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
|
||||
return maybe_suppress_result(c, result_used, node);
|
||||
}
|
||||
case clang::StringLiteral::UTF16:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");
|
||||
return nullptr;
|
||||
@ -3085,6 +3163,12 @@ static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::
|
||||
return trans_create_node(c, NodeTypeContinue);
|
||||
}
|
||||
|
||||
static AstNode *trans_predefined_expr(Context *c, ResultUsed result_used, TransScope *scope,
|
||||
const clang::PredefinedExpr *expr)
|
||||
{
|
||||
return trans_string_literal(c, result_used, scope, expr->getFunctionName());
|
||||
}
|
||||
|
||||
static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_scope, AstNode *result_node) {
|
||||
if (result_node == nullptr)
|
||||
return ErrorUnexpected;
|
||||
@ -3109,7 +3193,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
|
||||
trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
|
||||
case clang::Stmt::IntegerLiteralClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
|
||||
trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt));
|
||||
case clang::Stmt::ConditionalOperatorClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
|
||||
@ -3121,7 +3205,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
|
||||
trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
|
||||
case clang::Stmt::ImplicitCastExprClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
|
||||
trans_implicit_cast_expr(c, result_used, scope, (const clang::ImplicitCastExpr *)stmt));
|
||||
case clang::Stmt::DeclRefExprClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
|
||||
@ -3152,28 +3236,28 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
|
||||
case clang::Stmt::NullStmtClass:
|
||||
*out_node = nullptr;
|
||||
*out_node = trans_create_node(c, NodeTypeBlock);
|
||||
*out_child_scope = scope;
|
||||
return ErrorNone;
|
||||
case clang::Stmt::MemberExprClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
|
||||
trans_member_expr(c, result_used, scope, (const clang::MemberExpr *)stmt));
|
||||
case clang::Stmt::ArraySubscriptExprClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
|
||||
trans_array_subscript_expr(c, result_used, scope, (const clang::ArraySubscriptExpr *)stmt));
|
||||
case clang::Stmt::CStyleCastExprClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
|
||||
case clang::Stmt::UnaryExprOrTypeTraitExprClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
|
||||
trans_unary_expr_or_type_trait_expr(c, result_used, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
|
||||
case clang::Stmt::ForStmtClass: {
|
||||
AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
|
||||
return wrap_stmt(out_node, out_child_scope, scope, node);
|
||||
}
|
||||
case clang::Stmt::StringLiteralClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
|
||||
trans_string_literal(c, result_used, scope, (const clang::StringLiteral *)stmt));
|
||||
case clang::Stmt::BreakStmtClass:
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
|
||||
@ -3479,8 +3563,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
|
||||
return ErrorUnexpected;
|
||||
case clang::Stmt::PredefinedExprClass:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");
|
||||
return ErrorUnexpected;
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_predefined_expr(c, result_used, scope, (const clang::PredefinedExpr *)stmt));
|
||||
case clang::Stmt::PseudoObjectExprClass:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");
|
||||
return ErrorUnexpected;
|
||||
@ -3491,8 +3575,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");
|
||||
return ErrorUnexpected;
|
||||
case clang::Stmt::StmtExprClass:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
|
||||
return ErrorUnexpected;
|
||||
return wrap_stmt(out_node, out_child_scope, scope,
|
||||
trans_stmt_expr(c, result_used, scope, (const clang::StmtExpr *)stmt, out_node_scope));
|
||||
case clang::Stmt::SubstNonTypeTemplateParmExprClass:
|
||||
emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
|
||||
return ErrorUnexpected;
|
||||
|
@ -59,6 +59,40 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
);
|
||||
}
|
||||
|
||||
cases.add("predefined expressions",
|
||||
\\void foo(void) {
|
||||
\\ __func__;
|
||||
\\ __FUNCTION__;
|
||||
\\ __PRETTY_FUNCTION__;
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() void {
|
||||
\\ _ = c"foo";
|
||||
\\ _ = c"foo";
|
||||
\\ _ = c"void foo(void)";
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.add("ignore result",
|
||||
\\void foo() {
|
||||
\\ int a;
|
||||
\\ 1;
|
||||
\\ "hey";
|
||||
\\ 1 + 1;
|
||||
\\ 1 - 1;
|
||||
\\ a = 1;
|
||||
\\}
|
||||
,
|
||||
\\pub fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = 1;
|
||||
\\ _ = c"hey";
|
||||
\\ _ = (1 + 1);
|
||||
\\ _ = (1 - 1);
|
||||
\\ a = 1;
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.add("for loop with var init but empty body",
|
||||
\\void foo(void) {
|
||||
\\ for (int x = 0; x < 10; x++);
|
||||
@ -79,6 +113,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, // TODO this should be if (1 != 0) break
|
||||
\\pub fn foo() void {
|
||||
\\ while (true) {
|
||||
\\ {}
|
||||
\\ if (!1) break;
|
||||
\\ }
|
||||
\\}
|
||||
@ -511,11 +546,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return b;
|
||||
\\ else
|
||||
\\ return a;
|
||||
\\
|
||||
\\ if (a < b) ; else ;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ if (a < b) return b;
|
||||
\\ if (a < b) return b else return a;
|
||||
\\ if (a < b) {} else {}
|
||||
\\}
|
||||
);
|
||||
|
||||
@ -720,7 +758,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ ;;;;;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo() void {}
|
||||
\\pub export fn foo() void {
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\ {}
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.add("undefined array global",
|
||||
@ -751,6 +795,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.addC("void cast",
|
||||
\\void foo(int a) {
|
||||
\\ (void) a;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo(a: c_int) void {
|
||||
\\ _ = a;
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.addC("implicit cast to void *",
|
||||
\\void *foo(unsigned short *x) {
|
||||
\\ return x;
|
||||
@ -795,6 +849,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.addC("statement expression",
|
||||
\\int foo(void) {
|
||||
\\ return ({
|
||||
\\ int a = 1;
|
||||
\\ a;
|
||||
\\ });
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo() c_int {
|
||||
\\ return x: {
|
||||
\\ var a: c_int = 1;
|
||||
\\ break :x a;
|
||||
\\ };
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.addC("__extension__ cast",
|
||||
\\int foo(void) {
|
||||
\\ return __extension__ 1;
|
||||
\\}
|
||||
,
|
||||
\\pub export fn foo() c_int {
|
||||
\\ return 1;
|
||||
\\}
|
||||
);
|
||||
|
||||
cases.addC("bitshift",
|
||||
\\int foo(void) {
|
||||
\\ return (1 << 2) >> 1;
|
||||
@ -1425,52 +1505,52 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn bar() void {}
|
||||
);
|
||||
|
||||
cases.addC("u integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0U"
|
||||
,
|
||||
"pub const ZERO = c_uint(0);"
|
||||
cases.addC(
|
||||
"u integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0U",
|
||||
"pub const ZERO = c_uint(0);",
|
||||
);
|
||||
|
||||
cases.addC("l integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0L"
|
||||
,
|
||||
"pub const ZERO = c_long(0);"
|
||||
cases.addC(
|
||||
"l integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0L",
|
||||
"pub const ZERO = c_long(0);",
|
||||
);
|
||||
|
||||
cases.addC("ul integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0UL"
|
||||
,
|
||||
"pub const ZERO = c_ulong(0);"
|
||||
cases.addC(
|
||||
"ul integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0UL",
|
||||
"pub const ZERO = c_ulong(0);",
|
||||
);
|
||||
|
||||
cases.addC("lu integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0LU"
|
||||
,
|
||||
"pub const ZERO = c_ulong(0);"
|
||||
cases.addC(
|
||||
"lu integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0LU",
|
||||
"pub const ZERO = c_ulong(0);",
|
||||
);
|
||||
|
||||
cases.addC("ll integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0LL"
|
||||
,
|
||||
"pub const ZERO = c_longlong(0);"
|
||||
cases.addC(
|
||||
"ll integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0LL",
|
||||
"pub const ZERO = c_longlong(0);",
|
||||
);
|
||||
|
||||
cases.addC("ull integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0ULL"
|
||||
,
|
||||
"pub const ZERO = c_ulonglong(0);"
|
||||
cases.addC(
|
||||
"ull integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0ULL",
|
||||
"pub const ZERO = c_ulonglong(0);",
|
||||
);
|
||||
|
||||
cases.addC("llu integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0LLU"
|
||||
,
|
||||
"pub const ZERO = c_ulonglong(0);"
|
||||
cases.addC(
|
||||
"llu integer suffix after 0 (zero) in macro definition",
|
||||
"#define ZERO 0LLU",
|
||||
"pub const ZERO = c_ulonglong(0);",
|
||||
);
|
||||
|
||||
cases.addC("bitwise not on u-suffixed 0 (zero) in macro definition",
|
||||
"#define NOT_ZERO (~0U)"
|
||||
,
|
||||
"pub const NOT_ZERO = ~c_uint(0);"
|
||||
cases.addC(
|
||||
"bitwise not on u-suffixed 0 (zero) in macro definition",
|
||||
"#define NOT_ZERO (~0U)",
|
||||
"pub const NOT_ZERO = ~c_uint(0);",
|
||||
);
|
||||
|
||||
// cases.add("empty array with initializer",
|
||||
|
Loading…
x
Reference in New Issue
Block a user