@@ -793,6 +793,10 @@ fn visitVarDecl(c: *Context, var_decl: *const clang.VarDecl, mangled_name: ?[]co
793
793
var is_extern = storage_class == .Extern and ! has_init ;
794
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
800
const type_node = transQualTypeMaybeInitialized (c , scope , qual_type , decl_init , var_decl_loc ) catch | err | switch (err ) {
797
801
error .UnsupportedTranslation , error .UnsupportedType = > {
798
802
return failDecl (c , var_decl_loc , var_name , "unable to resolve variable type" , .{});
@@ -1839,6 +1843,7 @@ fn transDeclStmtOne(
1839
1843
.Var = > {
1840
1844
const var_decl = @ptrCast (* const clang .VarDecl , decl );
1841
1845
const decl_init = var_decl .getInit ();
1846
+ const loc = decl .getLocation ();
1842
1847
1843
1848
const qual_type = var_decl .getTypeSourceInfo_getType ();
1844
1849
const name = try c .str (@ptrCast (* const clang .NamedDecl , var_decl ).getName_bytes_begin ());
@@ -1848,12 +1853,12 @@ fn transDeclStmtOne(
1848
1853
// This is actually a global variable, put it in the global scope and reference it.
1849
1854
// `_ = mangled_name;`
1850
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
1860
const is_static_local = var_decl .isStaticLocal ();
1854
1861
const is_const = qual_type .isConstQualified ();
1855
-
1856
- const loc = decl .getLocation ();
1857
1862
const type_node = try transQualTypeMaybeInitialized (c , scope , qual_type , decl_init , loc );
1858
1863
1859
1864
var init_node = if (decl_init ) | expr |
@@ -4831,7 +4836,16 @@ fn qualTypeWasDemotedToOpaque(c: *Context, qt: clang.QualType) bool {
4831
4836
4832
4837
const record_decl = record_ty .getDecl ();
4833
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
4850
.Enum = > {
4837
4851
const enum_ty = @ptrCast (* const clang .EnumType , ty );
0 commit comments