authorgravatar for kavika@gmail.comMerlyn Morgan-Graham <kavika@gmail.com> 2019-12-16 01:33:27-08:00
committergravatar for kavika@gmail.comMerlyn Morgan-Graham <kavika@gmail.com> 2019-12-16 01:34:05-08:00
log89ef635b354062bebbe126e2be2f6e4540dc0db7
treebde3f956efb826d0984f020f46185b7964ba19fb
parentacff2d407b45519cc6dc24639dfe1289c899addd

Add boolean and, boolean or binary ops in translate-c-2


3 files changed, 505 insertions(+), 33 deletions(-)

src-self-hosted/clang.zig+10
...@@ -967,6 +967,16 @@ pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const Zig...@@ -967,6 +967,16 @@ pub extern fn ZigClangDeclRefExpr_getDecl(*const ZigClangDeclRefExpr) *const Zig
967pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;967pub extern fn ZigClangParenType_getInnerType(*const ZigClangParenType) ZigClangQualType;
968968
969pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;969pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) ZigClangQualType;
970pub extern fn ZigClangElaboratedType_getKeyword(*const ZigClangElaboratedType) ZigClangElaboratedTypeKeyword;
971pub const ZigClangElaboratedTypeKeyword = extern enum {
972 Struct,
973 Interface,
974 Union,
975 Class,
976 Enum,
977 Typename,
978 None,
979};
970980
971pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;981pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType;
972982
src-self-hosted/translate_c.zig+403-14
...@@ -592,14 +592,14 @@ fn transCreateNodeShiftOp(...@@ -592,14 +592,14 @@ fn transCreateNodeShiftOp(
592 const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);592 const rhs_location = ZigClangExpr_getBeginLoc(rhs_expr);
593 // lhs >> u5(rh)593 // lhs >> u5(rh)
594594
595 const lhs = try transExpr(rp, scope, lhs_expr, .used, .l_value);595 const lhs = try transExpr(rp, scope, lhs_expr, .used, .r_value);
596 const op_token = try appendToken(rp.c, op_tok_id, bytes);596 const op_token = try appendToken(rp.c, op_tok_id, bytes);
597597
598 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");598 const as_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
599 const rhs_type = try qualTypeToLog2IntRef(rp, ZigClangBinaryOperator_getType(stmt), rhs_location);599 const rhs_type = try qualTypeToLog2IntRef(rp, ZigClangBinaryOperator_getType(stmt), rhs_location);
600 try as_node.params.push(rhs_type);600 try as_node.params.push(rhs_type);
601 _ = try appendToken(rp.c, .Comma, ",");601 _ = try appendToken(rp.c, .Comma, ",");
602 const rhs = try transExpr(rp, scope, rhs_expr, .used, .l_value);602 const rhs = try transExpr(rp, scope, rhs_expr, .used, .r_value);
603 try as_node.params.push(rhs.node);603 try as_node.params.push(rhs.node);
604 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");604 as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
605605
...@@ -672,7 +672,7 @@ fn transBinaryOperator(...@@ -672,7 +672,7 @@ fn transBinaryOperator(
672 if (!cIsUnsignedInteger(qt)) {672 if (!cIsUnsignedInteger(qt)) {
673 // signed integer division uses @divTrunc673 // signed integer division uses @divTrunc
674 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");674 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");
675 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);675 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value);
676 try div_trunc_node.params.push(lhs.node);676 try div_trunc_node.params.push(lhs.node);
677 _ = try appendToken(rp.c, .Comma, ",");677 _ = try appendToken(rp.c, .Comma, ",");
678 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);678 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
...@@ -697,7 +697,7 @@ fn transBinaryOperator(...@@ -697,7 +697,7 @@ fn transBinaryOperator(
697 if (!cIsUnsignedInteger(qt)) {697 if (!cIsUnsignedInteger(qt)) {
698 // signed integer division uses @rem698 // signed integer division uses @rem
699 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");699 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
700 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);700 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value);
701 try rem_node.params.push(lhs.node);701 try rem_node.params.push(lhs.node);
702 _ = try appendToken(rp.c, .Comma, ",");702 _ = try appendToken(rp.c, .Comma, ",");
703 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);703 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
...@@ -806,10 +806,23 @@ fn transBinaryOperator(...@@ -806,10 +806,23 @@ fn transBinaryOperator(
806 .node_scope = scope,806 .node_scope = scope,
807 });807 });
808 },808 },
809 .LAnd,809 .LAnd => {
810 .LOr,810 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolAnd, .Keyword_and, "and");
811 .Comma,811 return maybeSuppressResult(rp, scope, result_used, TransResult{
812 => return revertAndWarn(812 .node = node,
813 .child_scope = scope,
814 .node_scope = scope,
815 });
816 },
817 .LOr => {
818 const node = try transCreateNodeBoolInfixOp(rp, scope, stmt, .BoolOr, .Keyword_or, "or");
819 return maybeSuppressResult(rp, scope, result_used, TransResult{
820 .node = node,
821 .child_scope = scope,
822 .node_scope = scope,
823 });
824 },
825 .Comma => return revertAndWarn(
813 rp,826 rp,
814 error.UnsupportedTranslation,827 error.UnsupportedTranslation,
815 ZigClangBinaryOperator_getBeginLoc(stmt),828 ZigClangBinaryOperator_getBeginLoc(stmt),
...@@ -1040,6 +1053,321 @@ fn transImplicitCastExpr(...@@ -1040,6 +1053,321 @@ fn transImplicitCastExpr(
1040 }1053 }
1041}1054}
10421055
1056fn toEnumZeroCmp(
1057 rp: RestorePoint,
1058 scope: *Scope,
1059 expr: *ast.Node,
1060 generate_enum_node: fn (RestorePoint, *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node,
1061 enum_ty: *const struct_ZigClangType,
1062 enum_source_loc: ZigClangSourceLocation,
1063) !*ast.Node {
1064 // expr != @bitCast(EnumType, @as(@TagType(EnumType), 0))
1065
1066 // @bitCast(Enum,
1067 const bitcast = try transCreateNodeBuiltinFnCall(rp.c, "@bitCast");
1068 const bitcast_enum_identifier = try generate_enum_node(rp, enum_ty, enum_source_loc);
1069 try bitcast.params.push(bitcast_enum_identifier);
1070 _ = try appendToken(rp.c, .Comma, ",");
1071
1072 // @as(
1073 const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as");
1074
1075 // @TagType(Enum),
1076 const tag_type = try transCreateNodeBuiltinFnCall(rp.c, "@TagType");
1077 const tag_type_enum_identifier = try generate_enum_node(rp, enum_ty, enum_source_loc);
1078 try tag_type.params.push(tag_type_enum_identifier);
1079 tag_type.rparen_token = try appendToken(rp.c, .RParen, ")");
1080 try cast_node.params.push(&tag_type.base);
1081 _ = try appendToken(rp.c, .Comma, ",");
1082
1083 // 0)
1084 const zero = try transCreateNodeInt(rp.c, 0);
1085 try cast_node.params.push(zero);
1086 cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
1087
1088 try bitcast.params.push(&cast_node.base);
1089 bitcast.rparen_token = try appendToken(rp.c, .RParen, ")");
1090
1091 // expr != @bitCast(EnumType, @as(@TagType(EnumType), 0))
1092 return transCreateNodeNotEqual(rp, scope, expr, &bitcast.base);
1093}
1094
1095fn transBoolExpr(
1096 rp: RestorePoint,
1097 scope: *Scope,
1098 expr: *const ZigClangExpr,
1099 used: ResultUsed,
1100 lrvalue: LRValue,
1101) !*ast.Node {
1102 var res = try transExpr(rp, scope, expr, used, lrvalue);
1103
1104 switch (res.node.id) {
1105 .InfixOp => switch (@ptrCast(*const ast.Node.InfixOp, &res.node).op) {
1106 .BoolOr,
1107 .BoolAnd,
1108 .EqualEqual,
1109 .BangEqual,
1110 .LessThan,
1111 .GreaterThan,
1112 .LessOrEqual,
1113 .GreaterOrEqual,
1114 => return res.node,
1115
1116 else => {},
1117 },
1118
1119 .PrefixOp => switch (@ptrCast(*const ast.Node.PrefixOp, &res.node).op) {
1120 .BoolNot => return res.node,
1121
1122 else => {},
1123 },
1124
1125 .BoolLiteral => return res.node,
1126
1127 else => {},
1128 }
1129
1130 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
1131
1132 switch (ZigClangType_getTypeClass(ty)) {
1133 .Builtin => {
1134 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
1135
1136 switch (ZigClangBuiltinType_getKind(builtin_ty)) {
1137 .Bool,
1138 .Char_U,
1139 .UChar,
1140 .Char_S,
1141 .SChar,
1142 .UShort,
1143 .UInt,
1144 .ULong,
1145 .ULongLong,
1146 .Short,
1147 .Int,
1148 .Long,
1149 .LongLong,
1150 .UInt128,
1151 .Int128,
1152 .Float,
1153 .Double,
1154 .Float128,
1155 .LongDouble,
1156 .WChar_U,
1157 .Char8,
1158 .Char16,
1159 .Char32,
1160 .WChar_S,
1161 .Float16,
1162 => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)),
1163
1164 .NullPtr => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)),
1165
1166 .Void,
1167 .Half,
1168 .ObjCId,
1169 .ObjCClass,
1170 .ObjCSel,
1171 .OMPArraySection,
1172 .Dependent,
1173 .Overload,
1174 .BoundMember,
1175 .PseudoObject,
1176 .UnknownAny,
1177 .BuiltinFn,
1178 .ARCUnbridgedCast,
1179 .OCLImage1dRO,
1180 .OCLImage1dArrayRO,
1181 .OCLImage1dBufferRO,
1182 .OCLImage2dRO,
1183 .OCLImage2dArrayRO,
1184 .OCLImage2dDepthRO,
1185 .OCLImage2dArrayDepthRO,
1186 .OCLImage2dMSAARO,
1187 .OCLImage2dArrayMSAARO,
1188 .OCLImage2dMSAADepthRO,
1189 .OCLImage2dArrayMSAADepthRO,
1190 .OCLImage3dRO,
1191 .OCLImage1dWO,
1192 .OCLImage1dArrayWO,
1193 .OCLImage1dBufferWO,
1194 .OCLImage2dWO,
1195 .OCLImage2dArrayWO,
1196 .OCLImage2dDepthWO,
1197 .OCLImage2dArrayDepthWO,
1198 .OCLImage2dMSAAWO,
1199 .OCLImage2dArrayMSAAWO,
1200 .OCLImage2dMSAADepthWO,
1201 .OCLImage2dArrayMSAADepthWO,
1202 .OCLImage3dWO,
1203 .OCLImage1dRW,
1204 .OCLImage1dArrayRW,
1205 .OCLImage1dBufferRW,
1206 .OCLImage2dRW,
1207 .OCLImage2dArrayRW,
1208 .OCLImage2dDepthRW,
1209 .OCLImage2dArrayDepthRW,
1210 .OCLImage2dMSAARW,
1211 .OCLImage2dArrayMSAARW,
1212 .OCLImage2dMSAADepthRW,
1213 .OCLImage2dArrayMSAADepthRW,
1214 .OCLImage3dRW,
1215 .OCLSampler,
1216 .OCLEvent,
1217 .OCLClkEvent,
1218 .OCLQueue,
1219 .OCLReserveID,
1220 .ShortAccum,
1221 .Accum,
1222 .LongAccum,
1223 .UShortAccum,
1224 .UAccum,
1225 .ULongAccum,
1226 .ShortFract,
1227 .Fract,
1228 .LongFract,
1229 .UShortFract,
1230 .UFract,
1231 .ULongFract,
1232 .SatShortAccum,
1233 .SatAccum,
1234 .SatLongAccum,
1235 .SatUShortAccum,
1236 .SatUAccum,
1237 .SatULongAccum,
1238 .SatShortFract,
1239 .SatFract,
1240 .SatLongFract,
1241 .SatUShortFract,
1242 .SatUFract,
1243 .SatULongFract,
1244 .OCLIntelSubgroupAVCMcePayload,
1245 .OCLIntelSubgroupAVCImePayload,
1246 .OCLIntelSubgroupAVCRefPayload,
1247 .OCLIntelSubgroupAVCSicPayload,
1248 .OCLIntelSubgroupAVCMceResult,
1249 .OCLIntelSubgroupAVCImeResult,
1250 .OCLIntelSubgroupAVCRefResult,
1251 .OCLIntelSubgroupAVCSicResult,
1252 .OCLIntelSubgroupAVCImeResultSingleRefStreamout,
1253 .OCLIntelSubgroupAVCImeResultDualRefStreamout,
1254 .OCLIntelSubgroupAVCImeSingleRefStreamin,
1255 .OCLIntelSubgroupAVCImeDualRefStreamin,
1256 => return res.node,
1257 }
1258 },
1259 .Pointer => return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeNullLiteral(rp.c)),
1260
1261 .Typedef => {
1262 return transCreateNodeNotEqual(rp, scope, res.node, try transCreateNodeInt(rp.c, 0)); // TODO currently assuming it is like an int/char/bool builtin type. Coerce the type and recurse? Add a toTypedefZeroCmp function?
1263
1264 // TODO This is the code that was in translate-c, but it seems like it is giving wrong results! It just prints the typedef name instead of the value
1265 // const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
1266 // const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
1267 // const typedef_name_decl = ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl);
1268
1269 // const typedef_name = if (rp.c.decl_table.get(@ptrToInt(typedef_name_decl))) |existing_entry|
1270 // existing_entry.value
1271 // else
1272 // try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, typedef_name_decl)));
1273
1274 // return transCreateNodeIdentifier(rp.c, typedef_name);
1275 },
1276
1277 .Enum => {
1278 const gen_enum_decl_node = struct {
1279 // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior,
1280 // and the code to generate the nodes is a little different for each case
1281 fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node {
1282 const actual_enum_ty = @ptrCast(*const ZigClangEnumType, enum_ty);
1283 const enum_decl = ZigClangEnumType_getDecl(actual_enum_ty);
1284 const enum_type = (try transEnumDecl(inner_rp.c, enum_decl)) orelse {
1285 return revertAndWarn(inner_rp, error.UnsupportedType, source_loc, "unable to translate enum declaration", .{});
1286 };
1287 return enum_type;
1288 }
1289 };
1290
1291 return toEnumZeroCmp(rp, scope, res.node, gen_enum_decl_node.generate_node, ty, ZigClangExpr_getBeginLoc(expr));
1292 },
1293
1294 .Elaborated => {
1295 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
1296
1297 switch (ZigClangElaboratedType_getKeyword(elaborated_ty)) {
1298 .Enum => {
1299 // Have to use a callback because node must be generated inline in order to avoid weird AST printing behavior,
1300 // and the code to generate the nodes is a little different for each case
1301 const gen_enum_type_node = struct {
1302 fn generate_node(inner_rp: RestorePoint, enum_ty: *const struct_ZigClangType, source_loc: ZigClangSourceLocation) TransError!*ast.Node {
1303 const inner_elaborated_ty = @ptrCast(*const ZigClangElaboratedType, enum_ty);
1304 const enum_type = try transQualType(inner_rp, ZigClangElaboratedType_getNamedType(inner_elaborated_ty), source_loc);
1305 return enum_type;
1306 }
1307 };
1308
1309 return toEnumZeroCmp(rp, scope, res.node, gen_enum_type_node.generate_node, ty, ZigClangExpr_getBeginLoc(expr));
1310 },
1311
1312 .Struct,
1313 .Union,
1314 .Interface,
1315 .Class,
1316 .Typename,
1317 .None,
1318 => return res.node,
1319 }
1320 },
1321
1322 .FunctionProto,
1323 .Record,
1324 .ConstantArray,
1325 .Paren,
1326 .Decayed,
1327 .Attributed,
1328 .IncompleteArray,
1329 .BlockPointer,
1330 .LValueReference,
1331 .RValueReference,
1332 .MemberPointer,
1333 .VariableArray,
1334 .DependentSizedArray,
1335 .DependentSizedExtVector,
1336 .Vector,
1337 .ExtVector,
1338 .FunctionNoProto,
1339 .UnresolvedUsing,
1340 .Adjusted,
1341 .TypeOfExpr,
1342 .TypeOf,
1343 .Decltype,
1344 .UnaryTransform,
1345 .TemplateTypeParm,
1346 .SubstTemplateTypeParm,
1347 .SubstTemplateTypeParmPack,
1348 .TemplateSpecialization,
1349 .Auto,
1350 .InjectedClassName,
1351 .DependentName,
1352 .DependentTemplateSpecialization,
1353 .PackExpansion,
1354 .ObjCObject,
1355 .ObjCInterface,
1356 .Complex,
1357 .ObjCObjectPointer,
1358 .Atomic,
1359 .Pipe,
1360 .ObjCTypeParam,
1361 .DeducedTemplateSpecialization,
1362 .DependentAddressSpace,
1363 .DependentVector,
1364 .MacroQualified,
1365 => return res.node,
1366 }
1367
1368 unreachable;
1369}
1370
1043fn transIntegerLiteral(1371fn transIntegerLiteral(
1044 rp: RestorePoint,1372 rp: RestorePoint,
1045 scope: *Scope,1373 scope: *Scope,
...@@ -1848,6 +2176,14 @@ fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {...@@ -1848,6 +2176,14 @@ fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {
1848 return ZigClangExpr_getType(expr);2176 return ZigClangExpr_getType(expr);
1849}2177}
18502178
2179fn getExprQualTypeBeforeImplicitCast(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {
2180 if (ZigClangExpr_getStmtClass(expr) == .ImplicitCastExprClass) {
2181 const cast_expr = @ptrCast(*const ZigClangImplicitCastExpr, expr);
2182 return getExprQualType(c, ZigClangImplicitCastExpr_getSubExpr(cast_expr));
2183 }
2184 return ZigClangExpr_getType(expr);
2185}
2186
1851fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool {2187fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool {
1852 switch (ZigClangType_getTypeClass(ty)) {2188 switch (ZigClangType_getTypeClass(ty)) {
1853 .Builtin => {2189 .Builtin => {
...@@ -2000,25 +2336,24 @@ fn transCreateNodePrefixOp(...@@ -2000,25 +2336,24 @@ fn transCreateNodePrefixOp(
2000 return node;2336 return node;
2001}2337}
20022338
2003fn transCreateNodeInfixOp(2339fn transCreateNodeInfixOpImpl(
2004 rp: RestorePoint,2340 rp: RestorePoint,
2005 scope: *Scope,2341 scope: *Scope,
2006 stmt: *const ZigClangBinaryOperator,2342 lhs_node: *ast.Node,
2343 rhs_node: *ast.Node,
2007 op: ast.Node.InfixOp.Op,2344 op: ast.Node.InfixOp.Op,
2008 op_tok_id: std.zig.Token.Id,2345 op_tok_id: std.zig.Token.Id,
2009 bytes: []const u8,2346 bytes: []const u8,
2010 grouped: bool,2347 grouped: bool,
2011) !*ast.Node {2348) !*ast.Node {
2012 const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;2349 const lparen = if (grouped) try appendToken(rp.c, .LParen, "(") else undefined;
2013 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
2014 const op_token = try appendToken(rp.c, op_tok_id, bytes);2350 const op_token = try appendToken(rp.c, op_tok_id, bytes);
2015 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
2016 const node = try rp.c.a().create(ast.Node.InfixOp);2351 const node = try rp.c.a().create(ast.Node.InfixOp);
2017 node.* = ast.Node.InfixOp{2352 node.* = ast.Node.InfixOp{
2018 .op_token = op_token,2353 .op_token = op_token,
2019 .lhs = lhs.node,2354 .lhs = lhs_node,
2020 .op = op,2355 .op = op,
2021 .rhs = rhs.node,2356 .rhs = rhs_node,
2022 };2357 };
2023 if (!grouped) return &node.base;2358 if (!grouped) return &node.base;
2024 const rparen = try appendToken(rp.c, .RParen, ")");2359 const rparen = try appendToken(rp.c, .RParen, ")");
...@@ -2031,6 +2366,60 @@ fn transCreateNodeInfixOp(...@@ -2031,6 +2366,60 @@ fn transCreateNodeInfixOp(
2031 return &grouped_expr.base;2366 return &grouped_expr.base;
2032}2367}
20332368
2369fn transCreateNodeInfixOp(
2370 rp: RestorePoint,
2371 scope: *Scope,
2372 stmt: *const ZigClangBinaryOperator,
2373 op: ast.Node.InfixOp.Op,
2374 op_tok_id: std.zig.Token.Id,
2375 bytes: []const u8,
2376 grouped: bool,
2377) !*ast.Node {
2378 return transCreateNodeInfixOpImpl(
2379 rp,
2380 scope,
2381 (try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value)).node,
2382 (try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value)).node,
2383 op,
2384 op_tok_id,
2385 bytes,
2386 grouped,
2387 );
2388}
2389
2390fn transCreateNodeNotEqual(
2391 rp: RestorePoint,
2392 scope: *Scope,
2393 lhs_node: *ast.Node,
2394 rhs_node: *ast.Node,
2395) !*ast.Node {
2396 return transCreateNodeInfixOpImpl(rp, scope, lhs_node, rhs_node, .BangEqual, .BangEqual, "!=", true);
2397}
2398
2399fn transCreateNodeBoolInfixOp(
2400 rp: RestorePoint,
2401 scope: *Scope,
2402 stmt: *const ZigClangBinaryOperator,
2403 comptime op: ast.Node.InfixOp.Op,
2404 comptime op_tok_id: std.zig.Token.Id,
2405 comptime bytes: []const u8,
2406) !*ast.Node {
2407 if (!(op == .BoolAnd or op == .BoolOr)) {
2408 @compileError("op must be either .BoolAnd or .BoolOr");
2409 }
2410
2411 return transCreateNodeInfixOpImpl(
2412 rp,
2413 scope,
2414 try transBoolExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .r_value),
2415 try transBoolExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value),
2416 op,
2417 op_tok_id,
2418 bytes,
2419 true,
2420 );
2421}
2422
2034fn transCreateNodePtrType(2423fn transCreateNodePtrType(
2035 c: *Context,2424 c: *Context,
2036 is_const: bool,2425 is_const: bool,
test/translate_c.zig+92-19
...@@ -949,26 +949,99 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -949,26 +949,99 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
949 \\}949 \\}
950 });950 });
951951
952 cases.addC("logical and, logical or on none bool values",952 cases.addC("logical and, logical or, on non-bool values", // Note this gets cut off by extra C symbols being injected in middle: `pub const Foo = enum_Foo;`
953 \\int and_or_none_bool(int a, float b, void *c) {953 \\enum Foo {
954 \\ if (a && b) return 0;954 \\ FooA,
955 \\ if (b && c) return 1;955 \\ FooB,
956 \\ if (a && c) return 2;956 \\ FooC,
957 \\ if (a || b) return 3;957 \\};
958 \\ if (b || c) return 4;958 \\int and_or_non_bool(int a, float b, void *c) {
959 \\ if (a || c) return 5;959 \\ enum Foo d = FooA;
960 \\ return 6;960 \\ int e = (a && b);
961 \\}961 \\ int f = (b && c);
962 , &[_][]const u8{962 \\ int g = (a && c);
963 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {963 \\ int h = (a || b);
964 \\ if ((a != 0) and (b != 0)) return 0;964 \\ int i = (b || c);
965 \\ if ((b != 0) and (c != null)) return 1;965 \\ int j = (a || c);
966 \\ if ((a != 0) and (c != null)) return 2;966 \\ int k = (a || d);
967 \\ if ((a != 0) or (b != 0)) return 3;967 \\ int l = (d && b);
968 \\ if ((b != 0) or (c != null)) return 4;968 \\ int m = (c || d);
969 \\ if ((a != 0) or (c != null)) return 5;969 \\ return (((((((e + f) + g) + h) + i) + j) + k) + l) + m;
970 \\ return 6;
971 \\}970 \\}
971 , &[_][]const u8{
972 \\pub const FooA = enum_Foo.A;
973 \\pub const FooB = enum_Foo.B;
974 \\pub const FooC = enum_Foo.C;
975 \\pub const enum_Foo = extern enum {
976 \\ A,
977 \\ B,
978 \\ C,
979 \\};
980 \\pub export fn and_or_non_bool(a: c_int, b: f32, c: ?*c_void) c_int {
981 \\ var d: enum_Foo = @as(enum_Foo, FooA);
982 \\ var e: c_int = (a != 0) and (b != 0);
983 \\ var f: c_int = (b != 0) and (c != null);
984 \\ var g: c_int = (a != 0) and (c != null);
985 \\ var h: c_int = (a != 0) or (b != 0);
986 \\ var i: c_int = (b != 0) or (c != null);
987 \\ var j: c_int = (a != 0) or (c != null);
988 \\ var k: c_int = (a != 0) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));
989 \\ var l: c_int = (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0);
990 \\ var m: c_int = (c != null) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0)));
991 \\ return (((((((e + f) + g) + h) + i) + j) + k) + l) + m;
992 \\}
993 });
994
995 cases.add_2("logical and, logical or, on non-bool values, extra parens",
996 \\enum Foo {
997 \\ FooA,
998 \\ FooB,
999 \\ FooC,
1000 \\};
1001 \\typedef int SomeTypedef;
1002 \\int and_or_non_bool(int a, float b, void *c) {
1003 \\ enum Foo d = FooA;
1004 \\ int e = (a && b);
1005 \\ int f = (b && c);
1006 \\ int g = (a && c);
1007 \\ int h = (a || b);
1008 \\ int i = (b || c);
1009 \\ int j = (a || c);
1010 \\ int k = (a || d);
1011 \\ int l = (d && b);
1012 \\ int m = (c || d);
1013 \\ SomeTypedef td = 44;
1014 \\ int o = (td || b);
1015 \\ int p = (c && td);
1016 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
1017 \\}
1018 , &[_][]const u8{
1019 \\pub const FooA = enum_Foo.A;
1020 \\pub const FooB = enum_Foo.B;
1021 \\pub const FooC = enum_Foo.C;
1022 \\pub const enum_Foo = extern enum {
1023 \\ A,
1024 \\ B,
1025 \\ C,
1026 \\};
1027 \\pub const SomeTypedef = c_int;
1028 \\pub export fn and_or_non_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1029 \\ var d: enum_Foo = @as(enum_Foo, FooA);
1030 \\ var e: c_int = ((a != 0) and (b != 0));
1031 \\ var f: c_int = ((b != 0) and (c != null));
1032 \\ var g: c_int = ((a != 0) and (c != null));
1033 \\ var h: c_int = ((a != 0) or (b != 0));
1034 \\ var i: c_int = ((b != 0) or (c != null));
1035 \\ var j: c_int = ((a != 0) or (c != null));
1036 \\ var k: c_int = ((a != 0) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))));
1037 \\ var l: c_int = ((@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))) and (b != 0));
1038 \\ var m: c_int = ((c != null) or (@as(c_int, d) != @bitCast(enum_Foo, @as(@TagType(enum_Foo), 0))));
1039 \\ var td: SomeTypedef = 44;
1040 \\ var o: c_int = ((td != 0) or (b != 0));
1041 \\ var p: c_int = ((c != null) and (td != 0));
1042 \\ return ((((((((((e + f) + g) + h) + i) + j) + k) + l) + m) + o) + p);
1043 \\}
1044 \\pub const Foo = enum_Foo;
972 });1045 });
9731046
974 cases.addC("assign",1047 cases.addC("assign",