| ... | @@ -793,6 +793,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co | ... | @@ -793,6 +793,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co |
| 793 | var is_extern = storage_class == .Extern and !has_init; | 793 | var is_extern = storage_class == .Extern and !has_init; |
| 794 | var is_export = !is_extern and storage_class != .Static; | 794 | var is_export = !is_extern and storage_class != .Static; |
| 795 | | 795 | |
| | 796 | if (!is_extern and qualTypeWasDemotedToOpaque(c, qual_type)) { |
| | 797 | return failDecl(c, var_decl_loc, var_name, "non-extern variable has opaque type", .{}); |
| | 798 | } |
| | 799 | |
| 796 | const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) { | 800 | const type_node = transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, var_decl_loc) catch |err| switch (err) { |
| 797 | error.UnsupportedTranslation, error.UnsupportedType => { | 801 | error.UnsupportedTranslation, error.UnsupportedType => { |
| 798 | return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); | 802 | return failDecl(c, var_decl_loc, var_name, "unable to resolve variable type", .{}); |
| ... | @@ -1839,6 +1843,7 @@ fn transDeclStmtOne( | ... | @@ -1839,6 +1843,7 @@ fn transDeclStmtOne( |
| 1839 | .Var => { | 1843 | .Var => { |
| 1840 | const var_decl = @ptrCast(*const clang.VarDecl, decl); | 1844 | const var_decl = @ptrCast(*const clang.VarDecl, decl); |
| 1841 | const decl_init = var_decl.getInit(); | 1845 | const decl_init = var_decl.getInit(); |
| | 1846 | const loc = decl.getLocation(); |
| 1842 | | 1847 | |
| 1843 | const qual_type = var_decl.getTypeSourceInfo_getType(); | 1848 | const qual_type = var_decl.getTypeSourceInfo_getType(); |
| 1844 | const name = try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin()); | 1849 | const name = try c.str(@ptrCast(*const clang.NamedDecl, var_decl).getName_bytes_begin()); |
| ... | @@ -1848,12 +1853,12 @@ fn transDeclStmtOne( | ... | @@ -1848,12 +1853,12 @@ fn transDeclStmtOne( |
| 1848 | // This is actually a global variable, put it in the global scope and reference it. | 1853 | // This is actually a global variable, put it in the global scope and reference it. |
| 1849 | // `_ = mangled_name;` | 1854 | // `_ = mangled_name;` |
| 1850 | return visitVarDecl(c, var_decl, mangled_name); | 1855 | return visitVarDecl(c, var_decl, mangled_name); |
| | 1856 | } else if (qualTypeWasDemotedToOpaque(c, qual_type)) { |
| | 1857 | return fail(c, error.UnsupportedTranslation, loc, "local variable has opaque type", .{}); |
| 1851 | } | 1858 | } |
| 1852 | | 1859 | |
| 1853 | const is_static_local = var_decl.isStaticLocal(); | 1860 | const is_static_local = var_decl.isStaticLocal(); |
| 1854 | const is_const = qual_type.isConstQualified(); | 1861 | const is_const = qual_type.isConstQualified(); |
| 1855 | | | |
| 1856 | const loc = decl.getLocation(); | | |
| 1857 | const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc); | 1862 | const type_node = try transQualTypeMaybeInitialized(c, scope, qual_type, decl_init, loc); |
| 1858 | | 1863 | |
| 1859 | var init_node = if (decl_init) |expr| | 1864 | var init_node = if (decl_init) |expr| |
| ... | @@ -4831,7 +4836,16 @@ fn qualTypeWasDemotedToOpaque(c: *Context, qt: clang.QualType) bool { | ... | @@ -4831,7 +4836,16 @@ fn qualTypeWasDemotedToOpaque(c: *Context, qt: clang.QualType) bool { |
| 4831 | | 4836 | |
| 4832 | const record_decl = record_ty.getDecl(); | 4837 | const record_decl = record_ty.getDecl(); |
| 4833 | const canonical = @ptrToInt(record_decl.getCanonicalDecl()); | 4838 | const canonical = @ptrToInt(record_decl.getCanonicalDecl()); |
| 4834 | return c.opaque_demotes.contains(canonical); | 4839 | if (c.opaque_demotes.contains(canonical)) return true; |
| | 4840 | |
| | 4841 | // check all childern for opaque types. |
| | 4842 | var it = record_decl.field_begin(); |
| | 4843 | const end_it = record_decl.field_end(); |
| | 4844 | while (it.neq(end_it)) : (it = it.next()) { |
| | 4845 | const field_decl = it.deref(); |
| | 4846 | if (qualTypeWasDemotedToOpaque(c, field_decl.getType())) return true; |
| | 4847 | } |
| | 4848 | return false; |
| 4835 | }, | 4849 | }, |
| 4836 | .Enum => { | 4850 | .Enum => { |
| 4837 | const enum_ty = @ptrCast(*const clang.EnumType, ty); | 4851 | const enum_ty = @ptrCast(*const clang.EnumType, ty); |