Browse Source

cf_flags (#7887)

* [typer] add `cf_flags`

* remove `cf_final`

* remove `cf_extern`

* CfPrivate -> CfPublic to better match previous behavior

* fix

* remove `cf_public`

* fix
Simon Krajewski 6 years ago
parent
commit
4a196e9c99

+ 2 - 2
src/codegen/codegen.ml

@@ -190,7 +190,7 @@ let fix_override com c f fd =
 				);
 				);
 			} in
 			} in
 			(* as3 does not allow wider visibility, so the base method has to be made public *)
 			(* as3 does not allow wider visibility, so the base method has to be made public *)
-			if Common.defined com Define.As3 && f.cf_public then f2.cf_public <- true;
+			if Common.defined com Define.As3 && has_class_field_flag f CfPublic then add_class_field_flag f2 CfPublic;
 			let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in
 			let targs = List.map (fun(v,c) -> (v.v_name, Option.is_some c, v.v_type)) nargs in
 			let fde = (match f.cf_expr with None -> assert false | Some e -> e) in
 			let fde = (match f.cf_expr with None -> assert false | Some e -> e) in
 			f.cf_expr <- Some { fde with eexpr = TFunction fd2 };
 			f.cf_expr <- Some { fde with eexpr = TFunction fd2 };
@@ -303,7 +303,7 @@ module Dump = struct
 				let rec print_field stat f =
 				let rec print_field stat f =
 					print "\n\t%s%s%s%s%s %s%s"
 					print "\n\t%s%s%s%s%s %s%s"
 						(s_metas f.cf_meta "\t")
 						(s_metas f.cf_meta "\t")
-						(if (f.cf_public && not (c.cl_extern || c.cl_interface)) then "public " else "")
+						(if (has_class_field_flag f CfPublic && not (c.cl_extern || c.cl_interface)) then "public " else "")
 						(if stat then "static " else "")
 						(if stat then "static " else "")
 						(match f.cf_kind with
 						(match f.cf_kind with
 							| Var v when (is_inline_var f.cf_kind) -> "inline "
 							| Var v when (is_inline_var f.cf_kind) -> "inline "

+ 1 - 1
src/codegen/gencommon/closuresToClass.ml

@@ -463,7 +463,7 @@ let configure gen ft =
 				let pos = cls.cl_pos in
 				let pos = cls.cl_pos in
 				let cf = mk_class_field "Delegate" (TFun(fun_args tfunc.tf_args, tfunc.tf_type)) true pos (Method MethNormal) [] in
 				let cf = mk_class_field "Delegate" (TFun(fun_args tfunc.tf_args, tfunc.tf_type)) true pos (Method MethNormal) [] in
 				cf.cf_expr <- Some { fexpr with eexpr = TFunction { tfunc with tf_expr = func_expr }; };
 				cf.cf_expr <- Some { fexpr with eexpr = TFunction { tfunc with tf_expr = func_expr }; };
-				cf.cf_final <- true;
+				add_class_field_flag cf CfFinal;
 				cls.cl_ordered_fields <- cf :: cls.cl_ordered_fields;
 				cls.cl_ordered_fields <- cf :: cls.cl_ordered_fields;
 				cls.cl_fields <- PMap.add cf.cf_name cf cls.cl_fields;
 				cls.cl_fields <- PMap.add cf.cf_name cf cls.cl_fields;
 				(* invoke function body: call Delegate function *)
 				(* invoke function body: call Delegate function *)

+ 1 - 1
src/codegen/gencommon/dynamicFieldAccess.ml

@@ -89,7 +89,7 @@ let configure gen (is_dynamic:texpr->Type.tfield_access->bool) (change_expr:texp
 					assert false
 					assert false
 			with Not_found ->
 			with Not_found ->
 				match f with
 				match f with
-				| FStatic (cl, cf) when cf.cf_extern ->
+				| FStatic (cl, cf) when has_class_field_flag cf CfExtern ->
 					{ e with eexpr = TField ({ fexpr with eexpr = TTypeExpr decl }, FStatic (cl, cf)) }
 					{ e with eexpr = TField ({ fexpr with eexpr = TTypeExpr decl }, FStatic (cl, cf)) }
 				| _ ->
 				| _ ->
 					change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true)
 					change_expr e { fexpr with eexpr = TTypeExpr decl } (field_name f) None true)

+ 1 - 1
src/codegen/gencommon/enumToClass.ml

@@ -182,7 +182,7 @@ struct
 
 
 		let getTag_cf_type = tfun [] basic.tstring in
 		let getTag_cf_type = tfun [] basic.tstring in
 		let getTag_cf = mk_class_field "getTag" getTag_cf_type true pos (Method MethNormal) [] in
 		let getTag_cf = mk_class_field "getTag" getTag_cf_type true pos (Method MethNormal) [] in
-		getTag_cf.cf_final <- true;
+		add_class_field_flag getTag_cf CfFinal;
 		getTag_cf.cf_expr <- Some {
 		getTag_cf.cf_expr <- Some {
 			eexpr = TFunction {
 			eexpr = TFunction {
 				tf_args = [];
 				tf_args = [];

+ 1 - 1
src/codegen/gencommon/fixOverrides.ml

@@ -207,7 +207,7 @@ let run ~explicit_fn_name ~get_vmtype gen =
 								f.cf_meta <- (Meta.Overload, [], f.cf_pos) :: f.cf_meta;
 								f.cf_meta <- (Meta.Overload, [], f.cf_pos) :: f.cf_meta;
 							if Meta.has Meta.Overload f.cf_meta then begin
 							if Meta.has Meta.Overload f.cf_meta then begin
 								(* if it is overload, create another field with the requested type *)
 								(* if it is overload, create another field with the requested type *)
-								let f3 = mk_class_field f.cf_name t f.cf_public f.cf_pos f.cf_kind f.cf_params in
+								let f3 = mk_class_field f.cf_name t (has_class_field_flag f CfPublic) f.cf_pos f.cf_kind f.cf_params in
 								let p = f.cf_pos in
 								let p = f.cf_pos in
 								let old_args, old_ret = get_fun f.cf_type in
 								let old_args, old_ret = get_fun f.cf_type in
 								let args, ret = get_fun t in
 								let args, ret = get_fun t in

+ 2 - 3
src/codegen/gencommon/gencommon.ml

@@ -1083,8 +1083,7 @@ let rec replace_mono t =
 
 
 (* helper *)
 (* helper *)
 let mk_class_field name t public pos kind params =
 let mk_class_field name t public pos kind params =
-	let f = mk_field name t pos null_pos in
-	f.cf_public <- public;
+	let f = mk_field name ~public t pos null_pos in
 	f.cf_meta <- [ Meta.CompilerGenerated, [], null_pos ]; (* annotate that this class field was generated by the compiler *)
 	f.cf_meta <- [ Meta.CompilerGenerated, [], null_pos ]; (* annotate that this class field was generated by the compiler *)
 	f.cf_kind <- kind;
 	f.cf_kind <- kind;
 	f.cf_params <- params;
 	f.cf_params <- params;
@@ -1251,7 +1250,7 @@ let rec field_access gen (t:t) (field:string) : (tfield_access) =
 		| _ -> FNotFound
 		| _ -> FNotFound
 
 
 let field_access_esp gen t field = match field with
 let field_access_esp gen t field = match field with
-	| FStatic(cl,cf) | FInstance(cl,_,cf) when cf.cf_extern ->
+	| FStatic(cl,cf) | FInstance(cl,_,cf) when has_class_field_flag cf CfExtern ->
 		let static = match field with
 		let static = match field with
 			| FStatic _ -> true
 			| FStatic _ -> true
 			| _ -> false
 			| _ -> false

+ 1 - 1
src/codegen/gencommon/overloadingConstructor.ml

@@ -222,7 +222,7 @@ let create_static_ctor com ~empty_ctor_expr cl ctor follow_type =
 (* makes constructors that only call super() for the 'ctor' argument *)
 (* makes constructors that only call super() for the 'ctor' argument *)
 let clone_ctors com ctor sup stl cl =
 let clone_ctors com ctor sup stl cl =
 	let rec clone cf =
 	let rec clone cf =
-		let ncf = mk_class_field "new" (apply_params sup.cl_params stl cf.cf_type) cf.cf_public cf.cf_pos cf.cf_kind cf.cf_params in
+		let ncf = mk_class_field "new" (apply_params sup.cl_params stl cf.cf_type) (has_class_field_flag cf CfPublic) cf.cf_pos cf.cf_kind cf.cf_params in
 		if Meta.has Meta.Protected cf.cf_meta then
 		if Meta.has Meta.Protected cf.cf_meta then
 			ncf.cf_meta <- (Meta.Protected,[],ncf.cf_pos) :: ncf.cf_meta;
 			ncf.cf_meta <- (Meta.Protected,[],ncf.cf_pos) :: ncf.cf_meta;
 		let args, ret = get_fun ncf.cf_type in
 		let args, ret = get_fun ncf.cf_type in

+ 1 - 1
src/codegen/gencommon/realTypeParams.ml

@@ -720,7 +720,7 @@ struct
 							not (has_type_params cf_type)
 							not (has_type_params cf_type)
 						) cl.cl_ordered_fields
 						) cl.cl_ordered_fields
 					in
 					in
-					let fields = List.map (fun f -> mk_class_field f.cf_name f.cf_type f.cf_public f.cf_pos f.cf_kind f.cf_params) fields in
+					let fields = List.map (fun f -> mk_class_field f.cf_name f.cf_type (has_class_field_flag f CfPublic) f.cf_pos f.cf_kind f.cf_params) fields in
 					let fields = iface_cf :: fields in
 					let fields = iface_cf :: fields in
 					iface.cl_ordered_fields <- fields;
 					iface.cl_ordered_fields <- fields;
 					List.iter (fun f -> iface.cl_fields <- PMap.add f.cf_name f iface.cl_fields) fields;
 					List.iter (fun f -> iface.cl_fields <- PMap.add f.cf_name f iface.cl_fields) fields;

+ 4 - 4
src/codegen/genxml.ml

@@ -121,7 +121,7 @@ let rec gen_type ?(values=None) t =
 			if opt then follow_param t else t
 			if opt then follow_param t else t
 		) args in
 		) args in
 		node "f" (("a",names) :: values) (List.map gen_type (args @ [r]))
 		node "f" (("a",names) :: values) (List.map gen_type (args @ [r]))
-	| TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_public = false }) a.a_fields)
+	| TAnon a -> node "a" [] (pmap (fun f -> gen_field [] { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) }) a.a_fields)
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
 	| TLazy f -> gen_type (lazy_type f)
 	| TLazy f -> gen_type (lazy_type f)
 
 
@@ -171,8 +171,8 @@ and gen_field att f =
 		with Not_found ->
 		with Not_found ->
 			cf.cf_name
 			cf.cf_name
 	in
 	in
-	let att = if f.cf_public then ("public","1") :: att else att in
-	let att = if f.cf_final then ("final","1") :: att else att in
+	let att = if has_class_field_flag f CfPublic then ("public","1") :: att else att in
+	let att = if has_class_field_flag f CfFinal then ("final","1") :: att else att in
 	node (field_name f) att (gen_type ~values:(Some values) f.cf_type :: gen_meta f.cf_meta @ gen_doc_opt f.cf_doc @ overloads)
 	node (field_name f) att (gen_type ~values:(Some values) f.cf_type :: gen_meta f.cf_meta @ gen_doc_opt f.cf_doc @ overloads)
 
 
 let gen_constr e =
 let gen_constr e =
@@ -500,7 +500,7 @@ let generate_type com t =
 		p "%s" (String.concat "" (List.rev ext));
 		p "%s" (String.concat "" (List.rev ext));
 		p " {\n";
 		p " {\n";
 		let sort l =
 		let sort l =
-			let a = Array.of_list (List.filter (fun f -> f.cf_public && not (List.memq f c.cl_overrides)) l) in
+			let a = Array.of_list (List.filter (fun f -> has_class_field_flag f CfPublic && not (List.memq f c.cl_overrides)) l) in
 			let name = function "new" -> "" | n -> n in
 			let name = function "new" -> "" | n -> n in
 			Array.sort (fun f1 f2 ->
 			Array.sort (fun f1 f2 ->
 				match f1.cf_kind, f2.cf_kind with
 				match f1.cf_kind, f2.cf_kind with

+ 1 - 1
src/compiler/displayOutput.ml

@@ -441,7 +441,7 @@ module TypePathHandler = struct
 			in
 			in
 			let fields = match !statics with
 			let fields = match !statics with
 				| None -> types
 				| None -> types
-				| Some c -> types @ (List.map (make_field_doc c) (List.filter (fun cf -> cf.cf_public) c.cl_ordered_statics))
+				| Some c -> types @ (List.map (make_field_doc c) (List.filter (fun cf -> has_class_field_flag cf CfPublic) c.cl_ordered_statics))
 			in
 			in
 			let fields = match !enum_statics with
 			let fields = match !enum_statics with
 				| None -> fields
 				| None -> fields

+ 2 - 2
src/context/display/displayFields.ml

@@ -70,7 +70,7 @@ let collect_static_extensions ctx items e p =
 								acc
 								acc
 							else begin
 							else begin
 								let f = prepare_using_field f in
 								let f = prepare_using_field f in
-								let f = { f with cf_params = []; cf_public = true; cf_type = TFun(args,ret) } in
+								let f = { f with cf_params = []; cf_flags = set_flag f.cf_flags (int_of_class_field_flag CfPublic); cf_type = TFun(args,ret) } in
 								let decl = match c.cl_kind with
 								let decl = match c.cl_kind with
 									| KAbstractImpl a -> TAbstractDecl a
 									| KAbstractImpl a -> TAbstractDecl a
 									| _ -> TClassDecl c
 									| _ -> TClassDecl c
@@ -107,7 +107,7 @@ let collect ctx e_ast e dk with_type p =
 	let opt_args args ret = TFun(List.map(fun (n,o,t) -> n,true,t) args,ret) in
 	let opt_args args ret = TFun(List.map(fun (n,o,t) -> n,true,t) args,ret) in
 	let should_access c cf stat =
 	let should_access c cf stat =
 		if Meta.has Meta.NoCompletion cf.cf_meta then false
 		if Meta.has Meta.NoCompletion cf.cf_meta then false
-		else if c != ctx.curclass && not cf.cf_public && String.length cf.cf_name > 4 then begin match String.sub cf.cf_name 0 4 with
+		else if c != ctx.curclass && not (has_class_field_flag cf CfPublic) && String.length cf.cf_name > 4 then begin match String.sub cf.cf_name 0 4 with
 			| "get_" | "set_" -> false
 			| "get_" | "set_" -> false
 			| _ -> can_access ctx c cf stat
 			| _ -> can_access ctx c cf stat
 		end else
 		end else

+ 2 - 2
src/context/typecore.ml

@@ -308,7 +308,7 @@ let push_this ctx e = match e.eexpr with
 		er,fun () -> ctx.this_stack <- List.tl ctx.this_stack
 		er,fun () -> ctx.this_stack <- List.tl ctx.this_stack
 
 
 let is_removable_field ctx f =
 let is_removable_field ctx f =
-	f.cf_extern || Meta.has Meta.Generic f.cf_meta
+	has_class_field_flag f CfExtern || Meta.has Meta.Generic f.cf_meta
 	|| (match f.cf_kind with
 	|| (match f.cf_kind with
 		| Var {v_read = AccRequire (s,_)} -> true
 		| Var {v_read = AccRequire (s,_)} -> true
 		| Method MethMacro -> not ctx.in_macro
 		| Method MethMacro -> not ctx.in_macro
@@ -316,7 +316,7 @@ let is_removable_field ctx f =
 
 
 (** checks if we can access to a given class field using current context *)
 (** checks if we can access to a given class field using current context *)
 let rec can_access ctx ?(in_overload=false) c cf stat =
 let rec can_access ctx ?(in_overload=false) c cf stat =
-	if cf.cf_public then
+	if (has_class_field_flag cf CfPublic) then
 		true
 		true
 	else if not in_overload && ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta then
 	else if not in_overload && ctx.com.config.pf_overload && Meta.has Meta.Overload cf.cf_meta then
 		true
 		true

+ 2 - 2
src/core/display/completionItem.ml

@@ -163,14 +163,14 @@ module CompletionModuleType = struct
 			| Some c ->
 			| Some c ->
 				try
 				try
 					let cf = PMap.find "_new" c.cl_statics in
 					let cf = PMap.find "_new" c.cl_statics in
-					if c.cl_extern || cf.cf_public then Yes else YesButPrivate
+					if c.cl_extern || (has_class_field_flag cf CfPublic) then Yes else YesButPrivate
 				with Not_found ->
 				with Not_found ->
 					No
 					No
 		in
 		in
 		let ctor c =
 		let ctor c =
 			try
 			try
 				let _,cf = get_constructor (fun cf -> cf.cf_type) c in
 				let _,cf = get_constructor (fun cf -> cf.cf_type) c in
-				if c.cl_extern || cf.cf_public then Yes else YesButPrivate
+				if c.cl_extern || (has_class_field_flag cf CfPublic) then Yes else YesButPrivate
 			with Not_found ->
 			with Not_found ->
 				No
 				No
 		in
 		in

+ 2 - 2
src/core/json/genjson.ml

@@ -513,8 +513,8 @@ and generate_class_field' ctx cfs cf =
 	[
 	[
 		"name",jstring cf.cf_name;
 		"name",jstring cf.cf_name;
 		"type",generate_type ctx cf.cf_type;
 		"type",generate_type ctx cf.cf_type;
-		"isPublic",jbool cf.cf_public;
-		"isFinal",jbool cf.cf_final;
+		"isPublic",jbool (has_class_field_flag cf CfPublic);
+		"isFinal",jbool (has_class_field_flag cf CfFinal);
 		"params",jlist (generate_type_parameter ctx) cf.cf_params;
 		"params",jlist (generate_type_parameter ctx) cf.cf_params;
 		"meta",generate_metadata ctx cf.cf_meta;
 		"meta",generate_metadata ctx cf.cf_meta;
 		"kind",generate_class_kind ();
 		"kind",generate_class_kind ();

+ 37 - 15
src/core/type.ml

@@ -179,7 +179,6 @@ and texpr = {
 and tclass_field = {
 and tclass_field = {
 	mutable cf_name : string;
 	mutable cf_name : string;
 	mutable cf_type : t;
 	mutable cf_type : t;
-	mutable cf_public : bool;
 	cf_pos : pos;
 	cf_pos : pos;
 	cf_name_pos : pos;
 	cf_name_pos : pos;
 	mutable cf_doc : Ast.documentation;
 	mutable cf_doc : Ast.documentation;
@@ -189,8 +188,7 @@ and tclass_field = {
 	mutable cf_expr : texpr option;
 	mutable cf_expr : texpr option;
 	mutable cf_expr_unoptimized : tfunc option;
 	mutable cf_expr_unoptimized : tfunc option;
 	mutable cf_overloads : tclass_field list;
 	mutable cf_overloads : tclass_field list;
-	mutable cf_extern : bool; (* this is only true if the field itself is extern, not its class *)
-	mutable cf_final : bool;
+	mutable cf_flags : int;
 }
 }
 
 
 and tclass_kind =
 and tclass_kind =
@@ -381,6 +379,34 @@ type class_field_scope =
 	| CFSMember
 	| CFSMember
 	| CFSConstructor
 	| CFSConstructor
 
 
+type flag_tclass_field =
+	| CfPublic
+	| CfExtern (* This is only set if the field itself is extern, not just the class. *)
+	| CfFinal
+
+(* Flags *)
+
+let has_flag flags flag =
+	flags land (1 lsl flag) > 0
+
+let set_flag flags flag =
+	flags lor (1 lsl flag)
+
+let unset_flag flags flag =
+	flags land (lnot (1 lsl flag))
+
+let int_of_class_field_flag (flag : flag_tclass_field) =
+	Obj.magic flag
+
+let add_class_field_flag cf (flag : flag_tclass_field) =
+	cf.cf_flags <- set_flag cf.cf_flags (int_of_class_field_flag flag)
+
+let remove_class_field_flag cf (flag : flag_tclass_field) =
+	cf.cf_flags <- unset_flag cf.cf_flags (int_of_class_field_flag flag)
+
+let has_class_field_flag cf (flag : flag_tclass_field) =
+	has_flag cf.cf_flags (int_of_class_field_flag flag)
+
 (* ======= General utility ======= *)
 (* ======= General utility ======= *)
 
 
 let alloc_var =
 let alloc_var =
@@ -484,21 +510,19 @@ let module_extra file sign time kind policy =
 	}
 	}
 
 
 
 
-let mk_field name t p name_pos = {
+let mk_field name ?(public = true) t p name_pos = {
 	cf_name = name;
 	cf_name = name;
 	cf_type = t;
 	cf_type = t;
 	cf_pos = p;
 	cf_pos = p;
 	cf_name_pos = name_pos;
 	cf_name_pos = name_pos;
 	cf_doc = None;
 	cf_doc = None;
 	cf_meta = [];
 	cf_meta = [];
-	cf_public = true;
 	cf_kind = Var { v_read = AccNormal; v_write = AccNormal };
 	cf_kind = Var { v_read = AccNormal; v_write = AccNormal };
 	cf_expr = None;
 	cf_expr = None;
 	cf_expr_unoptimized = None;
 	cf_expr_unoptimized = None;
 	cf_params = [];
 	cf_params = [];
 	cf_overloads = [];
 	cf_overloads = [];
-	cf_extern = false;
-	cf_final = false;
+	cf_flags = if public then set_flag 0 (int_of_class_field_flag CfPublic) else 0;
 }
 }
 
 
 let null_module = {
 let null_module = {
@@ -1432,8 +1456,6 @@ module Printer = struct
 			"cf_name",cf.cf_name;
 			"cf_name",cf.cf_name;
 			"cf_doc",s_doc cf.cf_doc;
 			"cf_doc",s_doc cf.cf_doc;
 			"cf_type",s_type_kind (follow cf.cf_type);
 			"cf_type",s_type_kind (follow cf.cf_type);
-			"cf_public",string_of_bool cf.cf_public;
-			"cf_final",string_of_bool cf.cf_final;
 			"cf_pos",s_pos cf.cf_pos;
 			"cf_pos",s_pos cf.cf_pos;
 			"cf_name_pos",s_pos cf.cf_name_pos;
 			"cf_name_pos",s_pos cf.cf_name_pos;
 			"cf_meta",s_metadata cf.cf_meta;
 			"cf_meta",s_metadata cf.cf_meta;
@@ -1884,7 +1906,7 @@ let rec type_eq param a b =
 					if f1.cf_kind <> f2.cf_kind && (param = EqStrict || param = EqCoreType || not (unify_kind f1.cf_kind f2.cf_kind)) then error [invalid_kind n f1.cf_kind f2.cf_kind];
 					if f1.cf_kind <> f2.cf_kind && (param = EqStrict || param = EqCoreType || not (unify_kind f1.cf_kind f2.cf_kind)) then error [invalid_kind n f1.cf_kind f2.cf_kind];
 					let a = f1.cf_type and b = f2.cf_type in
 					let a = f1.cf_type and b = f2.cf_type in
 					(try type_eq param a b with Unify_error l -> error (invalid_field n :: l));
 					(try type_eq param a b with Unify_error l -> error (invalid_field n :: l));
-					if f1.cf_public != f2.cf_public then error [invalid_visibility n];
+					if (has_class_field_flag f1 CfPublic) != (has_class_field_flag f2 CfPublic) then error [invalid_visibility n];
 				with
 				with
 					Not_found ->
 					Not_found ->
 						if is_closed a2 then error [has_no_field b n];
 						if is_closed a2 then error [has_no_field b n];
@@ -2057,7 +2079,7 @@ let rec unify a b =
 				let _, ft, f1 = (try raw_class_field make_type c tl n with Not_found -> error [has_no_field a n]) in
 				let _, ft, f1 = (try raw_class_field make_type c tl n with Not_found -> error [has_no_field a n]) in
 				let ft = apply_params c.cl_params tl ft in
 				let ft = apply_params c.cl_params tl ft in
 				if not (unify_kind f1.cf_kind f2.cf_kind) then error [invalid_kind n f1.cf_kind f2.cf_kind];
 				if not (unify_kind f1.cf_kind f2.cf_kind) then error [invalid_kind n f1.cf_kind f2.cf_kind];
-				if f2.cf_public && not f1.cf_public then error [invalid_visibility n];
+				if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n];
 
 
 				(match f2.cf_kind with
 				(match f2.cf_kind with
 				| Var { v_read = AccNo } | Var { v_read = AccNever } ->
 				| Var { v_read = AccNo } | Var { v_read = AccNever } ->
@@ -2109,7 +2131,7 @@ let rec unify a b =
 				end;
 				end;
 				(match f1.cf_kind with
 				(match f1.cf_kind with
 				| Method MethInline ->
 				| Method MethInline ->
-					if (c.cl_extern || f1.cf_extern) && not (Meta.has Meta.Runtime f1.cf_meta) then error [Has_no_runtime_field (a,n)];
+					if (c.cl_extern || has_class_field_flag f1 CfExtern) && not (Meta.has Meta.Runtime f1.cf_meta) then error [Has_no_runtime_field (a,n)];
 				| _ -> ());
 				| _ -> ());
 			) an.a_fields;
 			) an.a_fields;
 			(match !(an.a_status) with
 			(match !(an.a_status) with
@@ -2142,7 +2164,7 @@ let rec unify a b =
 					if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq t1 t2 | _ -> false) tl) then error [cannot_unify a b]
 					if not (List.exists (fun t -> match follow t with TAbstract({a_path = ["haxe"],"Constructible"},[t2]) -> type_iseq t1 t2 | _ -> false) tl) then error [cannot_unify a b]
 				| _ ->
 				| _ ->
 					let _,t,cf = class_field c tl "new" in
 					let _,t,cf = class_field c tl "new" in
-					if not cf.cf_public then error [invalid_visibility "new"];
+					if not (has_class_field_flag cf CfPublic) then error [invalid_visibility "new"];
 					begin try unify t t1
 					begin try unify t t1
 					with Unify_error l -> error (cannot_unify a b :: l) end
 					with Unify_error l -> error (cannot_unify a b :: l) end
 			end
 			end
@@ -2225,7 +2247,7 @@ and unify_anons a b a1 a2 =
 				| Opened, Var { v_read = AccNormal; v_write = AccNo }, Var { v_read = AccNormal; v_write = AccNormal } ->
 				| Opened, Var { v_read = AccNormal; v_write = AccNo }, Var { v_read = AccNormal; v_write = AccNormal } ->
 					f1.cf_kind <- f2.cf_kind;
 					f1.cf_kind <- f2.cf_kind;
 				| _ -> error [invalid_kind n f1.cf_kind f2.cf_kind]);
 				| _ -> error [invalid_kind n f1.cf_kind f2.cf_kind]);
-			if f2.cf_public && not f1.cf_public then error [invalid_visibility n];
+			if (has_class_field_flag f2 CfPublic) && not (has_class_field_flag f1 CfPublic) then error [invalid_visibility n];
 			try
 			try
 				unify_with_access f1 (field_type f1) f2;
 				unify_with_access f1 (field_type f1) f2;
 				(match !(a1.a_status) with
 				(match !(a1.a_status) with
@@ -2374,7 +2396,7 @@ and unify_with_access f1 t1 f2 =
 	| Var { v_read = AccNo } | Var { v_read = AccNever } -> unify f2.cf_type t1
 	| Var { v_read = AccNo } | Var { v_read = AccNever } -> unify f2.cf_type t1
 	(* read only *)
 	(* read only *)
 	| Method MethNormal | Method MethInline | Var { v_write = AccNo } | Var { v_write = AccNever } ->
 	| Method MethNormal | Method MethInline | Var { v_write = AccNo } | Var { v_write = AccNever } ->
-		if f1.cf_final <> f2.cf_final then raise (Unify_error [FinalInvariance]);
+		if (has_class_field_flag f1 CfFinal) <> (has_class_field_flag f2 CfFinal) then raise (Unify_error [FinalInvariance]);
 		unify t1 f2.cf_type
 		unify t1 f2.cf_type
 	(* read/write *)
 	(* read/write *)
 	| _ -> with_variance (type_eq EqBothDynamic) t1 f2.cf_type
 	| _ -> with_variance (type_eq EqBothDynamic) t1 f2.cf_type

+ 1 - 1
src/filters/filters.ml

@@ -641,7 +641,7 @@ let check_cs_events com t = match t with
 		let check fields f =
 		let check fields f =
 			match f.cf_kind with
 			match f.cf_kind with
 			| Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event f.cf_meta ->
 			| Var { v_read = AccNormal; v_write = AccNormal } when Meta.has Meta.Event f.cf_meta ->
-				if f.cf_public then error "@:event fields must be private" f.cf_pos;
+				if (has_class_field_flag f CfPublic) then error "@:event fields must be private" f.cf_pos;
 
 
 				(* prevent generating reflect helpers for the event in gencommon *)
 				(* prevent generating reflect helpers for the event in gencommon *)
 				f.cf_meta <- (Meta.SkipReflection, [], f.cf_pos) :: f.cf_meta;
 				f.cf_meta <- (Meta.SkipReflection, [], f.cf_pos) :: f.cf_meta;

+ 3 - 3
src/generators/genas3.ml

@@ -996,7 +996,7 @@ let generate_field ctx static f =
 			print ctx "]";
 			print ctx "]";
 		| _ -> ()
 		| _ -> ()
 	) f.cf_meta;
 	) f.cf_meta;
-	let public = f.cf_public || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static)
+	let public = (has_class_field_flag f CfPublic) || Hashtbl.mem ctx.get_sets (f.cf_name,static) || (f.cf_name = "main" && static)
 		|| f.cf_name = "resolve" || Meta.has Meta.Public f.cf_meta
 		|| f.cf_name = "resolve" || Meta.has Meta.Public f.cf_meta
 		(* consider all abstract methods public to avoid issues with inlined private access *)
 		(* consider all abstract methods public to avoid issues with inlined private access *)
 	    || (match ctx.curclass.cl_kind with KAbstractImpl _ -> true | _ -> false)
 	    || (match ctx.curclass.cl_kind with KAbstractImpl _ -> true | _ -> false)
@@ -1005,7 +1005,7 @@ let generate_field ctx static f =
 	let p = ctx.curclass.cl_pos in
 	let p = ctx.curclass.cl_pos in
 	match f.cf_expr, f.cf_kind with
 	match f.cf_expr, f.cf_kind with
 	| Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) ->
 	| Some { eexpr = TFunction fd }, Method (MethNormal | MethInline) ->
-		print ctx "%s%s " rights (if static || not f.cf_final then "" else " final ");
+		print ctx "%s%s " rights (if static || not (has_class_field_flag f CfFinal) then "" else " final ");
 		let rec loop c =
 		let rec loop c =
 			match c.cl_super with
 			match c.cl_super with
 			| None -> ()
 			| None -> ()
@@ -1114,7 +1114,7 @@ let generate_class ctx c =
 	| Some f ->
 	| Some f ->
 		let f = { f with
 		let f = { f with
 			cf_name = snd c.cl_path;
 			cf_name = snd c.cl_path;
-			cf_public = true;
+			cf_flags = set_flag f.cf_flags (int_of_class_field_flag CfPublic);
 			cf_kind = Method MethNormal;
 			cf_kind = Method MethNormal;
 		} in
 		} in
 		ctx.constructor_block <- true;
 		ctx.constructor_block <- true;

+ 6 - 6
src/generators/gencs.ml

@@ -1909,10 +1909,10 @@ let generate con =
 			let fn_is_final = function
 			let fn_is_final = function
 				| None -> true
 				| None -> true
 				| Some ({ cf_kind = Method mkind } as m) ->
 				| Some ({ cf_kind = Method mkind } as m) ->
-					(match mkind with | MethInline -> true | _ -> false) || m.cf_final
+					(match mkind with | MethInline -> true | _ -> false) || (has_class_field_flag m CfFinal)
 				| _ -> assert false
 				| _ -> assert false
 			in
 			in
-			let is_virtual = not (is_interface || is_final || prop.cf_final || fn_is_final get || fn_is_final set) in
+			let is_virtual = not (is_interface || is_final || (has_class_field_flag prop CfFinal) || fn_is_final get || fn_is_final set) in
 
 
 			let fn_is_override = function
 			let fn_is_override = function
 				| Some cf -> List.memq cf cl.cl_overrides
 				| Some cf -> List.memq cf cl.cl_overrides
@@ -2047,7 +2047,7 @@ let generate con =
 					end (* TODO see how (get,set) variable handle when they are interfaces *)
 					end (* TODO see how (get,set) variable handle when they are interfaces *)
 				| Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
 				| Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
 					List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then
 					List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then
-						gen_class_field w ~is_overload:true is_static cl cf.cf_final cf
+						gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
 					) cf.cf_overloads
 					) cf.cf_overloads
 				| Var _ | Method MethDynamic -> ()
 				| Var _ | Method MethDynamic -> ()
 				| Method _ when is_new && Meta.has Meta.Struct cl.cl_meta && fst (get_fun cf.cf_type) = [] ->
 				| Method _ when is_new && Meta.has Meta.Struct cl.cl_meta && fst (get_fun cf.cf_type) = [] ->
@@ -2067,15 +2067,15 @@ let generate con =
 							| _ -> ());
 							| _ -> ());
 						List.iter (fun cf ->
 						List.iter (fun cf ->
 							if cl.cl_interface || cf.cf_expr <> None then
 							if cl.cl_interface || cf.cf_expr <> None then
-								gen_class_field w ~is_overload:true is_static cl cf.cf_final cf
+								gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
 						) cf.cf_overloads;
 						) cf.cf_overloads;
 				| Method mkind ->
 				| Method mkind ->
 					List.iter (fun cf ->
 					List.iter (fun cf ->
 						if cl.cl_interface || cf.cf_expr <> None then
 						if cl.cl_interface || cf.cf_expr <> None then
-							gen_class_field w ~is_overload:true is_static cl cf.cf_final cf
+							gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
 					) cf.cf_overloads;
 					) cf.cf_overloads;
 					let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in
 					let is_virtual = not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false in
-					let is_virtual = if not is_virtual || cf.cf_final then false else is_virtual in
+					let is_virtual = if not is_virtual || (has_class_field_flag cf CfFinal) then false else is_virtual in
 					let is_override = List.memq cf cl.cl_overrides in
 					let is_override = List.memq cf cl.cl_overrides in
 					let is_override = is_override || match cf.cf_name, follow cf.cf_type with
 					let is_override = is_override || match cf.cf_name, follow cf.cf_type with
 						| "Equals", TFun([_,_,targ], tret) ->
 						| "Equals", TFun([_,_,targ], tret) ->

+ 2 - 2
src/generators/genhl.ml

@@ -140,7 +140,7 @@ let is_to_string t =
 	| _ -> false
 	| _ -> false
 
 
 let is_extern_field f =
 let is_extern_field f =
-	not (Type.is_physical_field f) || (match f.cf_kind with Method MethNormal -> List.exists (fun (m,_,_) -> m = Meta.HlNative) f.cf_meta | _ -> false) || f.cf_extern
+	not (Type.is_physical_field f) || (match f.cf_kind with Method MethNormal -> List.exists (fun (m,_,_) -> m = Meta.HlNative) f.cf_meta | _ -> false) || has_class_field_flag f CfExtern
 
 
 let is_array_class name =
 let is_array_class name =
 	match name with
 	match name with
@@ -3242,7 +3242,7 @@ let generate_static ctx c f =
 	match f.cf_kind with
 	match f.cf_kind with
 	| Var _ ->
 	| Var _ ->
 		()
 		()
-	| Method _ when f.cf_extern ->
+	| Method _ when has_class_field_flag f CfExtern ->
 		()
 		()
 	| Method m ->
 	| Method m ->
 		let add_native lib name =
 		let add_native lib name =

+ 2 - 2
src/generators/genjava.ml

@@ -1929,13 +1929,13 @@ let generate con =
 				end (* TODO see how (get,set) variable handle when they are interfaces *)
 				end (* TODO see how (get,set) variable handle when they are interfaces *)
 			| Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
 			| Method _ when not (Type.is_physical_field cf) || (match cl.cl_kind, cf.cf_expr with | KAbstractImpl _, None -> true | _ -> false) ->
 				List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then
 				List.iter (fun cf -> if cl.cl_interface || cf.cf_expr <> None then
-					gen_class_field w ~is_overload:true is_static cl cf.cf_final cf
+					gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
 				) cf.cf_overloads
 				) cf.cf_overloads
 			| Var _ | Method MethDynamic -> ()
 			| Var _ | Method MethDynamic -> ()
 			| Method mkind ->
 			| Method mkind ->
 				List.iter (fun cf ->
 				List.iter (fun cf ->
 					if cl.cl_interface || cf.cf_expr <> None then
 					if cl.cl_interface || cf.cf_expr <> None then
-						gen_class_field w ~is_overload:true is_static cl cf.cf_final cf
+						gen_class_field w ~is_overload:true is_static cl (has_class_field_flag cf CfFinal) cf
 				) cf.cf_overloads;
 				) cf.cf_overloads;
 				let is_virtual = is_new || (not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false) in
 				let is_virtual = is_new || (not is_final && match mkind with | MethInline -> false | _ when not is_new -> true | _ -> false) in
 				let is_override = match cf.cf_name with
 				let is_override = match cf.cf_name with

+ 1 - 1
src/generators/genphp7.ml

@@ -3295,7 +3295,7 @@ class class_builder ctx (cls:tclass) =
 			Indicates if `field` should be declared as `final`
 			Indicates if `field` should be declared as `final`
 		*)
 		*)
 		method is_final_field (field:tclass_field) : bool =
 		method is_final_field (field:tclass_field) : bool =
-			field.cf_final
+			has_class_field_flag field CfFinal
 		(**
 		(**
 			Check if there is no native php constructor in inheritance chain of this class.
 			Check if there is no native php constructor in inheritance chain of this class.
 			E.g. `StsClass` does have a constructor while still can be called with `new StdClass()`.
 			E.g. `StsClass` does have a constructor while still can be called with `new StdClass()`.

+ 7 - 7
src/generators/genswf9.ml

@@ -1994,7 +1994,7 @@ let generate_field_kind ctx f c stat =
 			let m = generate_method ctx fdata stat f.cf_meta in
 			let m = generate_method ctx fdata stat f.cf_meta in
 			Some (HFMethod {
 			Some (HFMethod {
 				hlm_type = m;
 				hlm_type = m;
-				hlm_final = stat || f.cf_final;
+				hlm_final = stat || (has_class_field_flag f CfFinal);
 				hlm_override = not stat && (loop c name || loop c f.cf_name);
 				hlm_override = not stat && (loop c name || loop c f.cf_name);
 				hlm_kind = kind;
 				hlm_kind = kind;
 			})
 			})
@@ -2097,7 +2097,7 @@ let generate_class ctx c =
 		in
 		in
 		let rec loop_meta = function
 		let rec loop_meta = function
 			| [] ->
 			| [] ->
-				if not f.cf_public && ctx.swf_protected then
+				if not (has_class_field_flag f CfPublic) && ctx.swf_protected then
 					protect()
 					protect()
 				else
 				else
 					ident f.cf_name
 					ident f.cf_name
@@ -2134,12 +2134,12 @@ let generate_class ctx c =
 			} :: acc
 			} :: acc
 	) c.cl_fields [] in
 	) c.cl_fields [] in
 	let fields = if c.cl_path <> ctx.boot then fields else begin
 	let fields = if c.cl_path <> ctx.boot then fields else begin
+		let cf = {
+			(mk_field "init" ~public:(ctx.swc && ctx.swf_protected) (TFun ([],t_dynamic)) c.cl_pos null_pos) with
+			cf_kind = Method MethNormal;
+		} in
 		{
 		{
-			hlf_name = make_name {
-				(mk_field "init" (TFun ([],t_dynamic)) c.cl_pos null_pos) with
-				cf_public = ctx.swc && ctx.swf_protected;
-				cf_kind = Method MethNormal;
-			} false;
+			hlf_name = make_name cf false;
 			hlf_slot = 0;
 			hlf_slot = 0;
 			hlf_kind = (HFMethod {
 			hlf_kind = (HFMethod {
 				hlm_type = generate_inits ctx;
 				hlm_type = generate_inits ctx;

+ 1 - 1
src/macro/eval/evalJit.ml

@@ -372,7 +372,7 @@ and jit_expr jit return e =
 			let name = hash (field_name fa) in
 			let name = hash (field_name fa) in
 			let execs = List.map (jit_expr jit false) el in
 			let execs = List.map (jit_expr jit false) el in
 			let is_final c cf =
 			let is_final c cf =
-				c.cl_final || cf.cf_final ||
+				c.cl_final || (has_class_field_flag cf CfFinal) ||
 				(* In interp mode we can assume that a field is final if it is not overridden.
 				(* In interp mode we can assume that a field is final if it is not overridden.
 				   We cannot do that in macro mode because overriding fields might be added
 				   We cannot do that in macro mode because overriding fields might be added
 				   after jitting this call. *)
 				   after jitting this call. *)

+ 1 - 1
src/macro/eval/evalPrototype.ml

@@ -170,7 +170,7 @@ module PrototypeBuilder = struct
 end
 end
 
 
 let is_removable_field cf =
 let is_removable_field cf =
-	cf.cf_extern || Meta.has Meta.Generic cf.cf_meta
+	has_class_field_flag cf CfExtern || Meta.has Meta.Generic cf.cf_meta
 
 
 let is_persistent cf =
 let is_persistent cf =
 	Meta.has (Meta.Custom ":persistent") cf.cf_meta
 	Meta.has (Meta.Custom ":persistent") cf.cf_meta

+ 13 - 8
src/macro/macroApi.ml

@@ -882,7 +882,7 @@ and encode_cfield f =
 	encode_obj [
 	encode_obj [
 		"name", encode_string f.cf_name;
 		"name", encode_string f.cf_name;
 		"type", encode_lazy_type f.cf_type;
 		"type", encode_lazy_type f.cf_type;
-		"isPublic", vbool f.cf_public;
+		"isPublic", vbool (has_class_field_flag f CfPublic);
 		"params", encode_type_params f.cf_params;
 		"params", encode_type_params f.cf_params;
 		"meta", encode_meta f.cf_meta (fun m -> f.cf_meta <- m);
 		"meta", encode_meta f.cf_meta (fun m -> f.cf_meta <- m);
 		"expr", vfun0 (fun() ->
 		"expr", vfun0 (fun() ->
@@ -894,8 +894,8 @@ and encode_cfield f =
 		"namePos",encode_pos f.cf_name_pos;
 		"namePos",encode_pos f.cf_name_pos;
 		"doc", null encode_string f.cf_doc;
 		"doc", null encode_string f.cf_doc;
 		"overloads", encode_ref f.cf_overloads (encode_and_map_array encode_cfield) (fun() -> "overloads");
 		"overloads", encode_ref f.cf_overloads (encode_and_map_array encode_cfield) (fun() -> "overloads");
-		"isExtern", vbool f.cf_extern;
-		"isFinal", vbool f.cf_final;
+		"isExtern", vbool (has_class_field_flag f CfExtern);
+		"isFinal", vbool (has_class_field_flag f CfFinal);
 	]
 	]
 
 
 and encode_field_kind k =
 and encode_field_kind k =
@@ -1257,10 +1257,12 @@ let decode_field_kind v =
 	| _ -> raise Invalid_expr
 	| _ -> raise Invalid_expr
 
 
 let decode_cfield v =
 let decode_cfield v =
-	{
+	let public = decode_bool (field v "isPublic") in
+	let extern = decode_bool (field v "isExtern") in
+	let final = decode_bool (field v "isFinal") in
+	let cf = {
 		cf_name = decode_string (field v "name");
 		cf_name = decode_string (field v "name");
 		cf_type = decode_type (field v "type");
 		cf_type = decode_type (field v "type");
-		cf_public = decode_bool (field v "isPublic");
 		cf_pos = decode_pos (field v "pos");
 		cf_pos = decode_pos (field v "pos");
 		cf_name_pos = decode_pos (field v "namePos");
 		cf_name_pos = decode_pos (field v "namePos");
 		cf_doc = opt decode_string (field v "doc");
 		cf_doc = opt decode_string (field v "doc");
@@ -1270,9 +1272,12 @@ let decode_cfield v =
 		cf_expr = None;
 		cf_expr = None;
 		cf_expr_unoptimized = None;
 		cf_expr_unoptimized = None;
 		cf_overloads = decode_ref (field v "overloads");
 		cf_overloads = decode_ref (field v "overloads");
-		cf_extern = decode_bool (field v "isExtern");
-		cf_final = decode_bool (field v "isFinal");
-	}
+		cf_flags = 0;
+	} in
+	if public then add_class_field_flag cf CfPublic;
+	if extern then add_class_field_flag cf CfExtern;
+	if final then add_class_field_flag cf CfFinal;
+	cf
 
 
 let decode_efield v =
 let decode_efield v =
 	{
 	{

+ 1 - 1
src/optimization/analyzerTexpr.ml

@@ -1252,7 +1252,7 @@ module Purity = struct
 				| None ->
 				| None ->
 					if not (is_pure c cf) then taint node
 					if not (is_pure c cf) then taint node
 				(* TODO: The function code check shouldn't be here I guess. *)
 				(* TODO: The function code check shouldn't be here I guess. *)
-				| Some _ when (cf.cf_extern || Meta.has Meta.FunctionCode cf.cf_meta || Meta.has (Meta.HlNative) cf.cf_meta || Meta.has (Meta.HlNative) c.cl_meta) ->
+				| Some _ when (has_class_field_flag cf CfExtern || Meta.has Meta.FunctionCode cf.cf_meta || Meta.has (Meta.HlNative) cf.cf_meta || Meta.has (Meta.HlNative) c.cl_meta) ->
 					if not (is_pure c cf) then taint node
 					if not (is_pure c cf) then taint node
 				| Some e ->
 				| Some e ->
 					try
 					try

+ 1 - 1
src/optimization/inlineConstructors.ml

@@ -165,7 +165,7 @@ let inline_constructors ctx e =
 		if i < 0 then "n" ^ (string_of_int (-i))
 		if i < 0 then "n" ^ (string_of_int (-i))
 		else (string_of_int i)
 		else (string_of_int i)
 	in
 	in
-	let is_extern_ctor c cf = c.cl_extern || cf.cf_extern in
+	let is_extern_ctor c cf = c.cl_extern || has_class_field_flag cf CfExtern in
 	let make_expr_for_list (el:texpr list) (t:t) (p:pos): texpr = match el with
 	let make_expr_for_list (el:texpr list) (t:t) (p:pos): texpr = match el with
 		| [] -> mk (TBlock[]) ctx.t.tvoid p
 		| [] -> mk (TBlock[]) ctx.t.tvoid p
 		| [e] -> e
 		| [e] -> e

+ 1 - 1
src/optimization/optimizer.ml

@@ -407,7 +407,7 @@ let inline_constructors ctx e =
 		if i < 0 then "n" ^ (string_of_int (-i))
 		if i < 0 then "n" ^ (string_of_int (-i))
 		else (string_of_int i)
 		else (string_of_int i)
 	in
 	in
-	let is_extern_ctor c cf = c.cl_extern || cf.cf_extern in
+	let is_extern_ctor c cf = c.cl_extern || has_class_field_flag cf CfExtern in
 	let rec find_locals e = match e.eexpr with
 	let rec find_locals e = match e.eexpr with
 		| TVar(v,Some e1) ->
 		| TVar(v,Some e1) ->
 			find_locals e1;
 			find_locals e1;

+ 4 - 4
src/typing/calls.ml

@@ -12,7 +12,7 @@ let is_forced_inline c cf =
 	match c with
 	match c with
 	| Some { cl_extern = true } -> true
 	| Some { cl_extern = true } -> true
 	| Some { cl_kind = KAbstractImpl _ } -> true
 	| Some { cl_kind = KAbstractImpl _ } -> true
-	| _ when cf.cf_extern -> true
+	| _ when has_class_field_flag cf CfExtern -> true
 	| _ -> false
 	| _ -> false
 
 
 let make_call ctx e params t ?(force_inline=false) p =
 let make_call ctx e params t ?(force_inline=false) p =
@@ -388,7 +388,7 @@ let unify_field_call ctx fa el args ret p inline =
 					Some e
 					Some e
 			);
 			);
 			cf2.cf_kind <- cf.cf_kind;
 			cf2.cf_kind <- cf.cf_kind;
-			cf2.cf_public <- cf.cf_public;
+			if not (has_class_field_flag cf CfPublic) then remove_class_field_flag cf2 CfPublic;
 			let metadata = List.filter (fun (m,_,_) -> match m with
 			let metadata = List.filter (fun (m,_,_) -> match m with
 				| Meta.Generic -> false
 				| Meta.Generic -> false
 				| _ -> true
 				| _ -> true
@@ -458,7 +458,7 @@ let rec acc_get ctx g p =
 		| Some _ when not (ctx.com.display.dms_inline) ->
 		| Some _ when not (ctx.com.display.dms_inline) ->
 			mk (TField (e,cmode)) t p
 			mk (TField (e,cmode)) t p
 		| Some { eexpr = TFunction _ } ->
 		| Some { eexpr = TFunction _ } ->
-			let chk_class c = (c.cl_extern || f.cf_extern) && not (Meta.has Meta.Runtime f.cf_meta) in
+			let chk_class c = (c.cl_extern || has_class_field_flag f CfExtern) && not (Meta.has Meta.Runtime f.cf_meta) in
 			let wrap_extern c =
 			let wrap_extern c =
 				let c2 =
 				let c2 =
 					let m = c.cl_module in
 					let m = c.cl_module in
@@ -493,7 +493,7 @@ let rec acc_get ctx g p =
 					e_def
 					e_def
 				| TAnon a ->
 				| TAnon a ->
 					begin match !(a.a_status) with
 					begin match !(a.a_status) with
-						| Statics {cl_extern = false} when f.cf_extern ->
+						| Statics {cl_extern = false} when has_class_field_flag f CfExtern ->
 							display_error ctx "Cannot create closure on @:extern inline method" p;
 							display_error ctx "Cannot create closure on @:extern inline method" p;
 							e_def
 							e_def
 						| Statics c when chk_class c -> wrap_extern c
 						| Statics c when chk_class c -> wrap_extern c

+ 3 - 3
src/typing/fields.ml

@@ -155,13 +155,13 @@ let field_access ctx mode f fmode t e p =
 		match (match mode with MGet | MCall -> v.v_read | MSet -> v.v_write) with
 		match (match mode with MGet | MCall -> v.v_read | MSet -> v.v_write) with
 		| AccNo when not (Meta.has Meta.PrivateAccess ctx.meta) ->
 		| AccNo when not (Meta.has Meta.PrivateAccess ctx.meta) ->
 			(match follow e.etype with
 			(match follow e.etype with
-			| TInst (c,_) when is_parent c ctx.curclass || can_access ctx c { f with cf_public = false } false -> normal()
+			| TInst (c,_) when is_parent c ctx.curclass || can_access ctx c { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) } false -> normal()
 			| TAnon a ->
 			| TAnon a ->
 				(match !(a.a_status) with
 				(match !(a.a_status) with
 				| Opened when mode = MSet ->
 				| Opened when mode = MSet ->
 					f.cf_kind <- Var { v with v_write = AccNormal };
 					f.cf_kind <- Var { v with v_write = AccNormal };
 					normal()
 					normal()
-				| Statics c2 when ctx.curclass == c2 || can_access ctx c2 { f with cf_public = false } true -> normal()
+				| Statics c2 when ctx.curclass == c2 || can_access ctx c2 { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) } true -> normal()
 				| _ -> if ctx.untyped then normal() else AKNo f.cf_name)
 				| _ -> if ctx.untyped then normal() else AKNo f.cf_name)
 			| _ ->
 			| _ ->
 				if ctx.untyped then normal() else AKNo f.cf_name)
 				if ctx.untyped then normal() else AKNo f.cf_name)
@@ -416,7 +416,7 @@ let rec type_field ?(resume=false) ctx e i p mode =
 		(try
 		(try
 			let f = PMap.find i a.a_fields in
 			let f = PMap.find i a.a_fields in
 			if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then display_error ctx "Cannot access non-static abstract field statically" p;
 			if Meta.has Meta.Impl f.cf_meta && not (Meta.has Meta.Enum f.cf_meta) then display_error ctx "Cannot access non-static abstract field statically" p;
-			if not f.cf_public && not ctx.untyped then begin
+			if not (has_class_field_flag f CfPublic) && not ctx.untyped then begin
 				match !(a.a_status) with
 				match !(a.a_status) with
 				| Closed | Extend _ -> () (* always allow anon private fields access *)
 				| Closed | Extend _ -> () (* always allow anon private fields access *)
 				| Statics c when can_access ctx c f true -> ()
 				| Statics c when can_access ctx c f true -> ()

+ 4 - 4
src/typing/nullSafety.ml

@@ -126,11 +126,11 @@ let rec get_subject loose_safety expr =
 	match expr.eexpr with
 	match expr.eexpr with
 		| TLocal v ->
 		| TLocal v ->
 			SLocalVar v.v_id
 			SLocalVar v.v_id
-		| TField ({ eexpr = TTypeExpr _ }, FStatic (cls, field)) when loose_safety || field.cf_final ->
+		| TField ({ eexpr = TTypeExpr _ }, FStatic (cls, field)) when loose_safety || (has_class_field_flag field CfFinal) ->
 			SFieldOfClass (cls.cl_path, [field.cf_name])
 			SFieldOfClass (cls.cl_path, [field.cf_name])
-		| TField ({ eexpr = TConst TThis }, (FInstance (_, _, field) | FAnon field)) when loose_safety || field.cf_final ->
+		| TField ({ eexpr = TConst TThis }, (FInstance (_, _, field) | FAnon field)) when loose_safety || (has_class_field_flag field CfFinal) ->
 			SFieldOfThis [field.cf_name]
 			SFieldOfThis [field.cf_name]
-		| TField ({ eexpr = TLocal v }, (FInstance (_, _, field) | FAnon field)) when loose_safety || field.cf_final ->
+		| TField ({ eexpr = TLocal v }, (FInstance (_, _, field) | FAnon field)) when loose_safety || (has_class_field_flag field CfFinal) ->
 			SFieldOfLocalVar (v.v_id, [field.cf_name])
 			SFieldOfLocalVar (v.v_id, [field.cf_name])
 		| TField (e, (FInstance (_, _, field) | FAnon field)) when loose_safety ->
 		| TField (e, (FInstance (_, _, field) | FAnon field)) when loose_safety ->
 			(match get_subject loose_safety e with
 			(match get_subject loose_safety e with
@@ -466,7 +466,7 @@ class immediate_execution =
 							(* known to be pure *)
 							(* known to be pure *)
 							| { cl_path = ([], "Array") }, _ -> true
 							| { cl_path = ([], "Array") }, _ -> true
 							(* try to analyze function code *)
 							(* try to analyze function code *)
-							| _, ({ cf_expr = (Some { eexpr = TFunction fn }) } as field) when field.cf_final || not (is_overridden cls field) ->
+							| _, ({ cf_expr = (Some { eexpr = TFunction fn }) } as field) when (has_class_field_flag field CfFinal) || not (is_overridden cls field) ->
 								if arg_num < 0 || arg_num >= List.length fn.tf_args then
 								if arg_num < 0 || arg_num >= List.length fn.tf_args then
 									false
 									false
 								else begin
 								else begin

+ 7 - 8
src/typing/typeload.ml

@@ -502,14 +502,13 @@ and load_complex_type' ctx allow_display (t,p) =
 			) in
 			) in
 			let t = if Meta.has Meta.Optional f.cff_meta then ctx.t.tnull t else t in
 			let t = if Meta.has Meta.Optional f.cff_meta then ctx.t.tnull t else t in
 			let cf = {
 			let cf = {
-				(mk_field n t p (pos f.cff_name)) with
-				cf_public = !pub;
+				(mk_field n ~public:!pub t p (pos f.cff_name)) with
 				cf_kind = access;
 				cf_kind = access;
 				cf_params = !params;
 				cf_params = !params;
 				cf_doc = f.cff_doc;
 				cf_doc = f.cff_doc;
 				cf_meta = f.cff_meta;
 				cf_meta = f.cff_meta;
-				cf_final = !final;
 			} in
 			} in
+			if !final then add_class_field_flag cf CfFinal;
 			init_meta_overloads ctx None cf;
 			init_meta_overloads ctx None cf;
 			if ctx.is_display_file then begin
 			if ctx.is_display_file then begin
 				DisplayEmitter.check_display_metadata ctx cf.cf_meta;
 				DisplayEmitter.check_display_metadata ctx cf.cf_meta;
@@ -785,7 +784,7 @@ let init_core_api ctx c =
 		with Unify_error l ->
 		with Unify_error l ->
 			display_error ctx ("Field " ^ f.cf_name ^ " has different type than in core type") p;
 			display_error ctx ("Field " ^ f.cf_name ^ " has different type than in core type") p;
 			display_error ctx (error_msg (Unify l)) p);
 			display_error ctx (error_msg (Unify l)) p);
-		if f2.cf_public <> f.cf_public then error ("Field " ^ f.cf_name ^ " has different visibility than core type") p;
+		if (has_class_field_flag f2 CfPublic) <> (has_class_field_flag f CfPublic) then error ("Field " ^ f.cf_name ^ " has different visibility than core type") p;
 		(match f2.cf_doc with
 		(match f2.cf_doc with
 		| None -> f2.cf_doc <- f.cf_doc
 		| None -> f2.cf_doc <- f.cf_doc
 		| Some _ -> ());
 		| Some _ -> ());
@@ -806,22 +805,22 @@ let init_core_api ctx c =
 	in
 	in
 	let check_fields fcore fl =
 	let check_fields fcore fl =
 		PMap.iter (fun i f ->
 		PMap.iter (fun i f ->
-			if not f.cf_public then () else
+			if not (has_class_field_flag f CfPublic) then () else
 			let f2 = try PMap.find f.cf_name fl with Not_found -> error ("Missing field " ^ i ^ " required by core type") c.cl_pos in
 			let f2 = try PMap.find f.cf_name fl with Not_found -> error ("Missing field " ^ i ^ " required by core type") c.cl_pos in
 			compare_fields f f2;
 			compare_fields f f2;
 		) fcore;
 		) fcore;
 		PMap.iter (fun i f ->
 		PMap.iter (fun i f ->
 			let p = (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos) in
 			let p = (match f.cf_expr with None -> c.cl_pos | Some e -> e.epos) in
-			if f.cf_public && not (Meta.has Meta.Hack f.cf_meta) && not (PMap.mem f.cf_name fcore) && not (List.memq f c.cl_overrides) then error ("Public field " ^ i ^ " is not part of core type") p;
+			if (has_class_field_flag f CfPublic) && not (Meta.has Meta.Hack f.cf_meta) && not (PMap.mem f.cf_name fcore) && not (List.memq f c.cl_overrides) then error ("Public field " ^ i ^ " is not part of core type") p;
 		) fl;
 		) fl;
 	in
 	in
 	check_fields ccore.cl_fields c.cl_fields;
 	check_fields ccore.cl_fields c.cl_fields;
 	check_fields ccore.cl_statics c.cl_statics;
 	check_fields ccore.cl_statics c.cl_statics;
 	(match ccore.cl_constructor, c.cl_constructor with
 	(match ccore.cl_constructor, c.cl_constructor with
 	| None, None -> ()
 	| None, None -> ()
-	| Some { cf_public = false }, _ -> ()
+	| Some cf, _ when not (has_class_field_flag cf CfPublic) -> ()
 	| Some f, Some f2 -> compare_fields f f2
 	| Some f, Some f2 -> compare_fields f f2
-	| None, Some { cf_public = false } -> ()
+	| None, Some cf when not (has_class_field_flag cf CfPublic) -> ()
 	| _ -> error "Constructor differs from core type" c.cl_pos)
 	| _ -> error "Constructor differs from core type" c.cl_pos)
 
 
 let string_list_of_expr_path (e,p) =
 let string_list_of_expr_path (e,p) =

+ 4 - 4
src/typing/typeloadCheck.ml

@@ -147,7 +147,7 @@ let check_overriding ctx c f =
 				display_error ctx ("Field " ^ i ^ " should be declared with @:overload since it was already declared as @:overload in superclass") p
 				display_error ctx ("Field " ^ i ^ " should be declared with @:overload since it was already declared as @:overload in superclass") p
 			else if not (List.memq f c.cl_overrides) then
 			else if not (List.memq f c.cl_overrides) then
 				display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass " ^ s_type_path csup.cl_path) p
 				display_error ctx ("Field " ^ i ^ " should be declared with 'override' since it is inherited from superclass " ^ s_type_path csup.cl_path) p
-			else if not f.cf_public && f2.cf_public then
+			else if not (has_class_field_flag f CfPublic) && (has_class_field_flag f2 CfPublic) then
 				display_error ctx ("Field " ^ i ^ " has less visibility (public/private) than superclass one") p
 				display_error ctx ("Field " ^ i ^ " has less visibility (public/private) than superclass one") p
 			else (match f.cf_kind, f2.cf_kind with
 			else (match f.cf_kind, f2.cf_kind with
 			| _, Method MethInline ->
 			| _, Method MethInline ->
@@ -157,7 +157,7 @@ let check_overriding ctx c f =
 				() (* allow to redefine a method as inlined *)
 				() (* allow to redefine a method as inlined *)
 			| _ ->
 			| _ ->
 				display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p);
 				display_error ctx ("Field " ^ i ^ " has different property access than in superclass") p);
-			if f2.cf_final then display_error ctx ("Cannot override final method " ^ i) p;
+			if (has_class_field_flag f2 CfFinal) then display_error ctx ("Cannot override final method " ^ i) p;
 			try
 			try
 				let t = apply_params csup.cl_params params t in
 				let t = apply_params csup.cl_params params t in
 				valid_redefinition ctx f f.cf_type f2 t
 				valid_redefinition ctx f f.cf_type f2 t
@@ -324,7 +324,7 @@ module Inheritance = struct
 					| MethDynamic -> 1
 					| MethDynamic -> 1
 					| MethMacro -> 2
 					| MethMacro -> 2
 				in
 				in
-				if f.cf_public && not f2.cf_public && not (Meta.has Meta.CompilerGenerated f.cf_meta) then
+				if (has_class_field_flag f CfPublic) && not (has_class_field_flag f2 CfPublic) && not (Meta.has Meta.CompilerGenerated f.cf_meta) then
 					display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 					display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 				else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then
 				else if not (unify_kind f2.cf_kind f.cf_kind) || not (match f.cf_kind, f2.cf_kind with Var _ , Var _ -> true | Method m1, Method m2 -> mkind m1 = mkind m2 | _ -> false) then
 					display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p
 					display_error ctx ("Field " ^ i ^ " has different property access than in " ^ s_type_path intf.cl_path ^ " (" ^ s_kind f2.cf_kind ^ " should be " ^ s_kind f.cf_kind ^ ")") p
@@ -486,7 +486,7 @@ end
 let check_final_vars ctx e =
 let check_final_vars ctx e =
 	let final_vars = Hashtbl.create 0 in
 	let final_vars = Hashtbl.create 0 in
 	List.iter (fun cf -> match cf.cf_kind with
 	List.iter (fun cf -> match cf.cf_kind with
-		| Var _ when cf.cf_final && cf.cf_expr = None ->
+		| Var _ when (has_class_field_flag cf CfFinal) && cf.cf_expr = None ->
 			Hashtbl.add final_vars cf.cf_name cf
 			Hashtbl.add final_vars cf.cf_name cf
 		| _ ->
 		| _ ->
 			()
 			()

+ 9 - 12
src/typing/typeloadFields.ml

@@ -511,7 +511,7 @@ let is_public (ctx,cctx) access parent =
 	else if List.mem_assoc APublic access then
 	else if List.mem_assoc APublic access then
 		true
 		true
 	else match parent with
 	else match parent with
-		| Some { cf_public = p } -> p
+		| Some cf -> (has_class_field_flag cf CfPublic)
 		| _ -> c.cl_extern || c.cl_interface || cctx.extends_public
 		| _ -> c.cl_extern || c.cl_interface || cctx.extends_public
 
 
 let rec get_parent c name =
 let rec get_parent c name =
@@ -796,14 +796,13 @@ let create_variable (ctx,cctx,fctx) c f t eo p =
 		{ v_read = AccNormal ; v_write = AccNormal }
 		{ v_read = AccNormal ; v_write = AccNormal }
 	in
 	in
 	let cf = {
 	let cf = {
-		(mk_field (fst f.cff_name) t f.cff_pos (pos f.cff_name)) with
+		(mk_field (fst f.cff_name) ~public:(is_public (ctx,cctx) f.cff_access None) t f.cff_pos (pos f.cff_name)) with
 		cf_doc = f.cff_doc;
 		cf_doc = f.cff_doc;
 		cf_meta = f.cff_meta;
 		cf_meta = f.cff_meta;
 		cf_kind = Var kind;
 		cf_kind = Var kind;
-		cf_public = is_public (ctx,cctx) f.cff_access None;
-		cf_extern = fctx.is_extern;
-		cf_final = fctx.is_final;
 	} in
 	} in
+	if fctx.is_final then add_class_field_flag cf CfFinal;
+	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	ctx.curfield <- cf;
 	ctx.curfield <- cf;
 	bind_var (ctx,cctx,fctx) cf eo;
 	bind_var (ctx,cctx,fctx) cf eo;
 	cf
 	cf
@@ -1022,15 +1021,14 @@ let create_method (ctx,cctx,fctx) c f fd p =
 	let args = loop fd.f_args in
 	let args = loop fd.f_args in
 	let t = TFun (fun_args args,ret) in
 	let t = TFun (fun_args args,ret) in
 	let cf = {
 	let cf = {
-		(mk_field (fst f.cff_name) t f.cff_pos (pos f.cff_name)) with
+		(mk_field (fst f.cff_name) ~public:(is_public (ctx,cctx) f.cff_access parent) t f.cff_pos (pos f.cff_name)) with
 		cf_doc = f.cff_doc;
 		cf_doc = f.cff_doc;
 		cf_meta = f.cff_meta;
 		cf_meta = f.cff_meta;
 		cf_kind = Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
 		cf_kind = Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
-		cf_public = is_public (ctx,cctx) f.cff_access parent;
 		cf_params = params;
 		cf_params = params;
-		cf_extern = fctx.is_extern;
-		cf_final = fctx.is_final;
 	} in
 	} in
+	if fctx.is_final then add_class_field_flag cf CfFinal;
+	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	cf.cf_meta <- List.map (fun (m,el,p) -> match m,el with
 	cf.cf_meta <- List.map (fun (m,el,p) -> match m,el with
 		| Meta.AstSource,[] -> (m,(match fd.f_expr with None -> [] | Some e -> [e]),p)
 		| Meta.AstSource,[] -> (m,(match fd.f_expr with None -> [] | Some e -> [e]),p)
 		| _ -> m,el,p
 		| _ -> m,el,p
@@ -1243,13 +1241,12 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 	) in
 	) in
 	if (set = AccNormal && get = AccCall) || (set = AccNever && get = AccNever)  then error (name ^ ": Unsupported property combination") p;
 	if (set = AccNormal && get = AccCall) || (set = AccNever && get = AccNever)  then error (name ^ ": Unsupported property combination") p;
 	let cf = {
 	let cf = {
-		(mk_field name ret f.cff_pos (pos f.cff_name)) with
+		(mk_field name ~public:(is_public (ctx,cctx) f.cff_access None) ret f.cff_pos (pos f.cff_name)) with
 		cf_doc = f.cff_doc;
 		cf_doc = f.cff_doc;
 		cf_meta = f.cff_meta;
 		cf_meta = f.cff_meta;
 		cf_kind = Var { v_read = get; v_write = set };
 		cf_kind = Var { v_read = get; v_write = set };
-		cf_public = is_public (ctx,cctx) f.cff_access None;
-		cf_extern = fctx.is_extern;
 	} in
 	} in
+	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	ctx.curfield <- cf;
 	ctx.curfield <- cf;
 	bind_var (ctx,cctx,fctx) cf eo;
 	bind_var (ctx,cctx,fctx) cf eo;
 	cf
 	cf

+ 2 - 2
src/typing/typer.ml

@@ -1612,7 +1612,7 @@ and type_object_decl ctx fl with_type p =
 					| Some t -> t
 					| Some t -> t
 					| None ->
 					| None ->
 						let cf = PMap.find n field_map in
 						let cf = PMap.find n field_map in
-						if cf.cf_final then is_final := true;
+						if (has_class_field_flag cf CfFinal) then is_final := true;
 						if ctx.in_display && DisplayPosition.encloses_display_position pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn;
 						if ctx.in_display && DisplayPosition.encloses_display_position pn then DisplayEmitter.display_field ctx Unknown CFSMember cf pn;
 						cf.cf_type
 						cf.cf_type
 				in
 				in
@@ -1628,7 +1628,7 @@ and type_object_decl ctx fl with_type p =
 			if is_valid then begin
 			if is_valid then begin
 				if starts_with n '$' then error "Field names starting with a dollar are not allowed" p;
 				if starts_with n '$' then error "Field names starting with a dollar are not allowed" p;
 				let cf = mk_field n e.etype (punion pn e.epos) pn in
 				let cf = mk_field n e.etype (punion pn e.epos) pn in
-				if !is_final then cf.cf_final <- true;
+				if !is_final then add_class_field_flag cf CfFinal;
 				fields := PMap.add n cf !fields;
 				fields := PMap.add n cf !fields;
 			end;
 			end;
 			((n,pn,qs),e)
 			((n,pn,qs),e)