Commit 0816981561

Evan Haas <evan@lagerdata.com>
2021-02-24 08:25:11
translate-c: add typeof support
1 parent fd208d9
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;
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});
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<const clang::TypeOfType *>(self);
+    return bitcast(casted->getUnderlyingType());
+}
+
+const struct ZigClangExpr *ZigClangTypeOfExprType_getUnderlyingExpr(const struct ZigClangTypeOfExprType *self) {
+    auto casted = reinterpret_cast<const clang::TypeOfExprType *>(self);
+    return reinterpret_cast<const struct ZigClangExpr *>(casted->getUnderlyingExpr());
+}
+
 struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) {
     auto casted = reinterpret_cast<const clang::ElaboratedType *>(self);
     return bitcast(casted->getNamedType());
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 *);
 
test/run_translated_c.zig
@@ -1054,4 +1054,23 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
         \\    return 0;
         \\}
     , "");
+
+    cases.add("typeof operator",
+        \\#include <stdlib.h>
+        \\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;
+        \\}
+    , "");
 }