authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-09-20 19:49:41-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2017-09-20 19:49:41-07:00
logc10b052ceec96b0e927a3365708798a860696cbf
treeccd671961b80f8b55d4258b7de3b53def42e34e4
parenta5e4e205c8a9f2706300a4dc7ebe7cf3bfe093cd

translate expr++ from c to zig


1 files changed, 51 insertions(+), 8 deletions(-)

src/parsec.cpp+51-8
...@@ -386,8 +386,17 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) {...@@ -386,8 +386,17 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) {
386 return false;386 return false;
387}387}
388388
389static QualType resolve_any_typedef(Context *c, QualType qt) {
390 const Type * ty = qt.getTypePtr();
391 if (ty->getTypeClass() != Type::Typedef)
392 return qt;
393 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
394 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
395 return typedef_decl->getUnderlyingType();
396}
397
389static bool c_is_signed_integer(Context *c, QualType qt) {398static bool c_is_signed_integer(Context *c, QualType qt) {
390 const Type *c_type = qt.getTypePtr();399 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
391 if (c_type->getTypeClass() != Type::Builtin)400 if (c_type->getTypeClass() != Type::Builtin)
392 return false;401 return false;
393 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);402 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
...@@ -406,7 +415,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) {...@@ -406,7 +415,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) {
406}415}
407416
408static bool c_is_unsigned_integer(Context *c, QualType qt) {417static bool c_is_unsigned_integer(Context *c, QualType qt) {
409 const Type *c_type = qt.getTypePtr();418 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
410 if (c_type->getTypeClass() != Type::Builtin)419 if (c_type->getTypeClass() != Type::Builtin)
411 return false;420 return false;
412 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);421 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
...@@ -443,6 +452,16 @@ static bool c_is_float(Context *c, QualType qt) {...@@ -443,6 +452,16 @@ static bool c_is_float(Context *c, QualType qt) {
443 }452 }
444}453}
445454
455static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
456 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
457 // float and signed integer overflow is undefined behavior.
458 return false;
459 } else {
460 // unsigned integer overflow wraps around.
461 return true;
462 }
463}
464
446enum TransLRValue {465enum TransLRValue {
447 TransLValue,466 TransLValue,
448 TransRValue,467 TransRValue,
...@@ -1286,11 +1305,35 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue...@@ -1286,11 +1305,35 @@ static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue
1286 return trans_create_node_symbol(c, symbol_name);1305 return trans_create_node_symbol(c, symbol_name);
1287}1306}
12881307
1289static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) {1308static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) {
1290 switch (stmt->getOpcode()) {1309 switch (stmt->getOpcode()) {
1291 case UO_PostInc:1310 case UO_PostInc: {
1292 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc");1311 Expr *op_expr = stmt->getSubExpr();
1293 return nullptr;1312 BinOpType bin_op = qual_type_has_wrapping_overflow(c, op_expr->getType())
1313 ? BinOpTypeAssignPlusWrap
1314 : BinOpTypeAssignPlus;
1315
1316 if (!result_used) {
1317 // common case
1318 // c: expr++
1319 // zig: expr += 1
1320 return trans_create_node_bin_op(c,
1321 trans_expr(c, true, block, op_expr, TransLValue),
1322 bin_op,
1323 trans_create_node_unsigned(c, 1));
1324 } else {
1325 // worst case
1326 // c: expr++
1327 // zig: {
1328 // zig: const _ref = &expr;
1329 // zig: const _tmp = *_ref;
1330 // zig: *_ref += 1;
1331 // zig: _tmp
1332 // zig: }
1333 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc with result_used");
1334 return nullptr;
1335 }
1336 }
1294 case UO_PostDec:1337 case UO_PostDec:
1295 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec");1338 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec");
1296 return nullptr;1339 return nullptr;
...@@ -1312,7 +1355,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *...@@ -1312,7 +1355,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *
1312 case UO_Minus:1355 case UO_Minus:
1313 {1356 {
1314 Expr *op_expr = stmt->getSubExpr();1357 Expr *op_expr = stmt->getSubExpr();
1315 if (c_is_signed_integer(c, op_expr->getType()) || c_is_float(c, op_expr->getType())) {1358 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
1316 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);1359 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
1317 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;1360 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
13181361
...@@ -1642,7 +1685,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s...@@ -1642,7 +1685,7 @@ static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *s
1642 case Stmt::DeclRefExprClass:1685 case Stmt::DeclRefExprClass:
1643 return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue);1686 return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue);
1644 case Stmt::UnaryOperatorClass:1687 case Stmt::UnaryOperatorClass:
1645 return trans_unary_operator(c, block, (UnaryOperator *)stmt);1688 return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt);
1646 case Stmt::DeclStmtClass:1689 case Stmt::DeclStmtClass:
1647 return trans_local_declaration(c, block, (DeclStmt *)stmt);1690 return trans_local_declaration(c, block, (DeclStmt *)stmt);
1648 case Stmt::WhileStmtClass:1691 case Stmt::WhileStmtClass: