2
0
Эх сурвалжийг харах

forbid initialization of extern var fields unless they are static and can be inlined (fixed issue #1294)

Simon Krajewski 13 жил өмнө
parent
commit
4736e29bc0
1 өөрчлөгдсөн 31 нэмэгдсэн , 22 устгасан
  1. 31 22
      typeload.ml

+ 31 - 22
typeload.ml

@@ -1096,6 +1096,28 @@ let init_class ctx c p context_init herits fields =
 		let p = cf.cf_pos in
 		if not stat && has_field cf.cf_name c.cl_super then error ("Redefinition of variable " ^ cf.cf_name ^ " in subclass is not allowed") p;
 		let t = cf.cf_type in
+		let rec make_const e =
+			let e = ctx.g.do_optimize ctx e in
+			match e.eexpr with
+			| TConst _ -> Some e
+			| TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod) as op,e1,e2) -> (match make_const e1,make_const e2 with
+				| Some e1, Some e2 -> Some (mk (TBinop(op, e1, e2)) e.etype e.epos)
+				| _ -> None)
+			| TParenthesis e -> Some e
+			| TTypeExpr _ -> Some e
+			(* try to inline static function calls *)
+			| TCall ({ etype = TFun(_,ret); eexpr = TField ({ eexpr = TTypeExpr (TClassDecl c) },n) },el) ->
+				(try
+					let cf = PMap.find n c.cl_statics in
+					let func = match cf.cf_expr with Some ({eexpr = TFunction func}) -> func | _ -> raise Not_found in
+					let ethis = mk (TConst TThis) t_dynamic e.epos in
+					let inl = (try Optimizer.type_inline ctx cf func ethis el ret e.epos false with Error (Custom _,_) -> None) in
+					(match inl with
+					| None -> None
+					| Some e -> make_const e)
+				with Not_found -> None)
+			| _ -> None
+		in
 		match e with
 		| None -> ()
 		| Some e ->
@@ -1106,29 +1128,16 @@ let init_class ctx c p context_init herits fields =
 					if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
 					let e = type_var_field ctx t e stat p in
 					let e = (match cf.cf_kind with
+					| Var v when c.cl_extern || has_meta ":extern" cf.cf_meta ->
+						if not stat then begin
+							display_error ctx "Extern non-static variables may not be initialized" p;
+							e
+						end else begin
+							match make_const e with
+							| Some e -> e
+							| None -> display_error ctx "Extern variable initialization must be a constant value" p; e
+						end
 					| Var v when not stat || (v.v_read = AccInline && Common.defined ctx.com Define.Haxe3) ->
-						let rec make_const e =
-							let e = ctx.g.do_optimize ctx e in
-							match e.eexpr with
-							| TConst _ -> Some e
-							| TBinop ((OpAdd|OpSub|OpMult|OpDiv|OpMod) as op,e1,e2) -> (match make_const e1,make_const e2 with
-								| Some e1, Some e2 -> Some (mk (TBinop(op, e1, e2)) e.etype e.epos)
-								| _ -> None)
-							| TParenthesis e -> Some e
-							| TTypeExpr _ -> Some e
-							(* try to inline static function calls *)
-							| TCall ({ etype = TFun(_,ret); eexpr = TField ({ eexpr = TTypeExpr (TClassDecl c) },n) },el) ->
-								(try
-									let cf = PMap.find n c.cl_statics in
-									let func = match cf.cf_expr with Some ({eexpr = TFunction func}) -> func | _ -> raise Not_found in
-									let ethis = mk (TConst TThis) t_dynamic e.epos in
-									let inl = (try Optimizer.type_inline ctx cf func ethis el ret e.epos false with Error (Custom _,_) -> None) in
-									(match inl with
-									| None -> None
-									| Some e -> make_const e)
-								with Not_found -> None)
-							| _ -> None
-						in
 						let e = match make_const e with Some e -> e | None -> display_error ctx "Variable initialization must be a constant value" p; e in
 						e
 					| _ ->