diff --git a/src/clang.zig b/src/clang.zig index 270f477ddb..5ae4f50711 100644 --- a/src/clang.zig +++ b/src/clang.zig @@ -583,6 +583,16 @@ pub const MacroQualifiedType = opaque { extern fn ZigClangMacroQualifiedType_getModifiedType(*const MacroQualifiedType) QualType; }; +pub const TypeOfType = opaque { + pub const getUnderlyingType = ZigClangTypeOfType_getUnderlyingType; + extern fn ZigClangTypeOfType_getUnderlyingType(*const TypeOfType) QualType; +}; + +pub const TypeOfExprType = opaque { + pub const getUnderlyingExpr = ZigClangTypeOfExprType_getUnderlyingExpr; + extern fn ZigClangTypeOfExprType_getUnderlyingExpr(*const TypeOfExprType) *const Expr; +}; + pub const MemberExpr = opaque { pub const getBase = ZigClangMemberExpr_getBase; extern fn ZigClangMemberExpr_getBase(*const MemberExpr) *const Expr; diff --git a/src/translate_c.zig b/src/translate_c.zig index 4f1de2a617..42f11f473e 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -3827,6 +3827,20 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan const macroqualified_ty = @ptrCast(*const clang.MacroQualifiedType, ty); return transQualType(c, scope, macroqualified_ty.getModifiedType(), source_loc); }, + .TypeOf => { + const typeof_ty = @ptrCast(*const clang.TypeOfType, ty); + return transQualType(c, scope, typeof_ty.getUnderlyingType(), source_loc); + }, + .TypeOfExpr => { + const typeofexpr_ty = @ptrCast(*const clang.TypeOfExprType, ty); + const underlying_expr = transExpr(c, scope, typeofexpr_ty.getUnderlyingExpr(), .used) catch |err| switch (err) { + error.UnsupportedTranslation => { + return fail(c, error.UnsupportedType, source_loc, "unsupported underlying expression for TypeOfExpr", .{}); + }, + else => |e| return e, + }; + return Tag.typeof.create(c.arena, underlying_expr); + }, else => { const type_name = c.str(ty.getTypeClassName()); return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name}); diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index d9e5e527ac..8387f6fa80 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -2599,6 +2599,16 @@ struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct return bitcast(casted->getModifiedType()); } +struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const struct ZigClangTypeOfType *self) { + auto casted = reinterpret_cast(self); + return bitcast(casted->getUnderlyingType()); +} + +const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *self) { + auto casted = reinterpret_cast(self); + return reinterpret_cast(casted->getUnderlyingExpr()); +} + struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) { auto casted = reinterpret_cast(self); return bitcast(casted->getNamedType()); diff --git a/src/zig_clang.h b/src/zig_clang.h index a697c58b4f..3c3e97f4a3 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -1157,6 +1157,10 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(co ZIG_EXTERN_C struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *); +ZIG_EXTERN_C struct ZigClangQualType ZigClangTypeOfType_getUnderlyingType(const struct ZigClangTypeOfType *); + +ZIG_EXTERN_C const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *); + ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *); ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *); diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index 61569678c3..70dc1c835d 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -1054,4 +1054,23 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); + + cases.add("typeof operator", + \\#include + \\static int FOO = 42; + \\typedef typeof(FOO) foo_type; + \\typeof(foo_type) myfunc(typeof(FOO) x) { return (typeof(FOO)) x; } + \\int main(void) { + \\ int x = FOO; + \\ typeof(x) y = x; + \\ foo_type z = y; + \\ if (x != y) abort(); + \\ if (myfunc(z) != x) abort(); + \\ + \\ const char *my_string = "bar"; + \\ typeof (typeof (my_string)[4]) string_arr = {"a","b","c","d"}; + \\ if (string_arr[0][0] != 'a' || string_arr[3][0] != 'd') abort(); + \\ return 0; + \\} + , ""); }