aboutsummaryrefslogtreecommitdiffstats
path: root/cparser
diff options
context:
space:
mode:
Diffstat (limited to 'cparser')
-rw-r--r--cparser/Cutil.ml5
-rw-r--r--cparser/Cutil.mli2
-rw-r--r--cparser/Elab.ml89
3 files changed, 59 insertions, 37 deletions
diff --git a/cparser/Cutil.ml b/cparser/Cutil.ml
index 4b4e1b81..c8966941 100644
--- a/cparser/Cutil.ml
+++ b/cparser/Cutil.ml
@@ -1026,6 +1026,7 @@ let formatloc pp (filename, lineno) =
if filename <> "" then Format.fprintf pp "%s:%d: " filename lineno
(* Generate the default initializer for the given type *)
+exception No_default_init
let rec default_init env ty =
match unroll env ty with
@@ -1049,11 +1050,11 @@ let rec default_init env ty =
| TUnion(id, _) ->
let ci = Env.find_union env id in
begin match ci.ci_members with
- | [] -> assert false
+ | [] -> raise No_default_init
| fld :: _ -> Init_union(id, fld, default_init env fld.fld_typ)
end
| _ ->
- assert false
+ raise No_default_init
(* Substitution of variables by expressions *)
diff --git a/cparser/Cutil.mli b/cparser/Cutil.mli
index 91b073ab..8d461e5c 100644
--- a/cparser/Cutil.mli
+++ b/cparser/Cutil.mli
@@ -244,6 +244,8 @@ val formatloc: Format.formatter -> location -> unit
(* Printer for locations (for Format) *)
(* Initializers *)
+exception No_default_init
+ (* Raised if no default initilaizer exists *)
val default_init: Env.t -> typ -> init
(* Return a default initializer for the given type
diff --git a/cparser/Elab.ml b/cparser/Elab.ml
index 8cd7ed64..f8d2cb77 100644
--- a/cparser/Elab.ml
+++ b/cparser/Elab.ml
@@ -184,8 +184,8 @@ let enter_or_refine_ident local loc env s sto ty =
let elab_expr_f : (cabsloc -> Env.t -> Cabs.expression -> C.exp * Env.t) ref
= ref (fun _ _ _ -> assert false)
-let elab_funbody_f : (C.typ -> Env.t -> statement -> C.stmt) ref
- = ref (fun _ _ _ -> assert false)
+let elab_funbody_f : (C.typ -> bool -> Env.t -> statement -> C.stmt) ref
+ = ref (fun _ _ _ _ -> assert false)
(** * Elaboration of constants - C99 section 6.4.4 *)
@@ -1287,7 +1287,16 @@ and elab_single zi a il =
(* Start with top-level object initialized to default *)
-in elab_item (I.top env root ty_root) ie []
+in
+if is_function_type env ty_root then begin
+ error loc "illegal initializer (only variables can be initialized)";
+ raise Exit
+end;
+try
+ elab_item (I.top env root ty_root) ie []
+with No_default_init ->
+ error loc "variable has incomplete type %a" Cprint.typ ty_root;
+ raise Exit
(* Elaboration of a top-level initializer *)
@@ -1323,7 +1332,7 @@ let elab_initializer loc env root ty ie =
(* Elaboration of expressions *)
-let elab_expr loc env a =
+let elab_expr vararg loc env a =
let err fmt = error loc fmt in (* non-fatal error *)
let error fmt = fatal_error loc fmt in
@@ -1400,6 +1409,8 @@ let elab_expr loc env a =
(elaboration) --> __builtin_va_arg(ap, sizeof(ty))
*)
| CALL((VARIABLE "__builtin_va_start" as a1), [a2; a3]) ->
+ if not vararg then
+ err "'va_start' used in function with fixed args";
let b1,env = elab env a1 in
let b2,env = elab env a2 in
let _b3,env = elab env a3 in
@@ -1464,7 +1475,7 @@ let elab_expr loc env a =
(* 6.5.4 Cast operators *)
| CAST ((spec, dcl), SINGLE_INIT a1) ->
- let (ty, _) = elab_type loc env spec dcl in
+ let (ty, env) = elab_type loc env spec dcl in
let b1,env = elab env a1 in
if not (wrap2 valid_cast loc env b1.etyp ty) then
err "illegal cast from %a@ to %a" Cprint.typ b1.etyp Cprint.typ ty;
@@ -1473,7 +1484,7 @@ let elab_expr loc env a =
(* 6.5.2.5 Compound literals *)
| CAST ((spec, dcl), ie) ->
- let (ty, _) = elab_type loc env spec dcl in
+ let (ty, env) = elab_type loc env spec dcl in
begin match elab_initializer loc env "<compound literal>" ty ie with
| (ty', Some i) -> { edesc = ECompound(ty', i); etyp = ty' },env
| (ty', None) -> error "ill-formed compound literal"
@@ -1484,7 +1495,7 @@ let elab_expr loc env a =
| EXPR_SIZEOF a1 ->
let b1,env = elab env a1 in
if wrap incomplete_type loc env b1.etyp then
- err "incomplete type %a" Cprint.typ b1.etyp;
+ error "incomplete type %a" Cprint.typ b1.etyp;
let bdesc =
(* Catch special cases sizeof("string literal") *)
match b1.edesc with
@@ -1501,19 +1512,19 @@ let elab_expr loc env a =
| TYPE_SIZEOF (spec, dcl) ->
let (ty, env') = elab_type loc env spec dcl in
if wrap incomplete_type loc env' ty then
- err "incomplete type %a" Cprint.typ ty;
+ error "incomplete type %a" Cprint.typ ty;
{ edesc = ESizeof ty; etyp = TInt(size_t_ikind(), []) },env'
| EXPR_ALIGNOF a1 ->
let b1,env = elab env a1 in
if wrap incomplete_type loc env b1.etyp then
- err "incomplete type %a" Cprint.typ b1.etyp;
+ error "incomplete type %a" Cprint.typ b1.etyp;
{ edesc = EAlignof b1.etyp; etyp = TInt(size_t_ikind(), []) },env
| TYPE_ALIGNOF (spec, dcl) ->
let (ty, env') = elab_type loc env spec dcl in
if wrap incomplete_type loc env' ty then
- err "incomplete type %a" Cprint.typ ty;
+ error "incomplete type %a" Cprint.typ ty;
{ edesc = EAlignof ty; etyp = TInt(size_t_ikind(), []) },env
| UNARY(PLUS, a1) ->
@@ -1881,16 +1892,16 @@ let elab_expr loc env a =
in elab env a
(* Filling in forward declaration *)
-let _ = elab_expr_f := elab_expr
+let _ = elab_expr_f := (elab_expr false)
-let elab_opt_expr loc env = function
+let elab_opt_expr vararg loc env = function
| None -> None,env
- | Some a -> let a,env = (elab_expr loc env a) in
+ | Some a -> let a,env = (elab_expr vararg loc env a) in
Some a,env
-let elab_for_expr loc env = function
+let elab_for_expr vararg loc env = function
| None -> { sdesc = Sskip; sloc = elab_loc loc },env
- | Some a -> let a,env = elab_expr loc env a in
+ | Some a -> let a,env = elab_expr vararg loc env a in
{ sdesc = Sdo a; sloc = elab_loc loc },env
(* Handling of __func__ (section 6.4.2.2) *)
@@ -1942,6 +1953,8 @@ let enter_decdefs local loc env sto dl =
initializer can refer to the ident *)
let (id, sto', env1, ty, linkage) =
enter_or_refine_ident local loc env s sto1 ty in
+ if not isfun && is_void_type env ty then
+ fatal_error loc "'%s' has incomplete type" s;
(* process the initializer *)
let (ty', init') = elab_initializer loc env1 s ty init in
(* update environment with refined type *)
@@ -2103,9 +2116,13 @@ let elab_fundef env spec name defs body loc =
(* Enter function in the environment, for recursive references *)
let (fun_id, sto1, env1, _, _) =
enter_or_refine_ident false loc env1 s sto ty in
+ let incomplete_param env ty =
+ if wrap incomplete_type loc env ty then
+ fatal_error loc "parameter has incomplete type" in
(* Enter parameters and extra declarations in the environment *)
let env2 =
- List.fold_left (fun e (id, ty) -> Env.add_ident e id Storage_default ty)
+ List.fold_left (fun e (id, ty) -> incomplete_param e ty;
+ Env.add_ident e id Storage_default ty)
(Env.new_scope env1) params in
let env2 =
List.fold_left (fun e (sto, id, ty, init) -> Env.add_ident e id sto ty)
@@ -2117,7 +2134,7 @@ let elab_fundef env spec name defs body loc =
emit_elab ~debuginfo:false env3 loc
(Gdecl(Storage_static, func_id, func_ty, Some func_init));
(* Elaborate function body *)
- let body1 = !elab_funbody_f ty_ret env3 body in
+ let body1 = !elab_funbody_f ty_ret vararg env3 body in
(* Special treatment of the "main" function *)
let body2 =
if s = "main" then begin
@@ -2189,9 +2206,9 @@ and elab_definitions local env = function
(* Extended asm *)
-let elab_asm_operand loc env (ASMOPERAND(label, wide, chars, e)) =
+let elab_asm_operand vararg loc env (ASMOPERAND(label, wide, chars, e)) =
let s = elab_simple_string loc wide chars in
- let e',env = elab_expr loc env e in
+ let e',env = elab_expr vararg loc env e in
(label, s, e'),env
@@ -2203,7 +2220,8 @@ type stmt_context = {
ctx_return_typ: typ; (**r return type for the function *)
ctx_labels: StringSet.t; (**r all labels defined in the function *)
ctx_break: bool; (**r is 'break' allowed? *)
- ctx_continue: bool (**r is 'continue' allowed? *)
+ ctx_continue: bool; (**r is 'continue' allowed? *)
+ ctx_vararg: bool; (**r is this a vararg function? *)
}
let stmt_labels stmt =
@@ -2240,7 +2258,7 @@ let rec elab_stmt env ctx s =
(* 6.8.3 Expression statements *)
| COMPUTATION(a, loc) ->
- let a,env = (elab_expr loc env a) in
+ let a,env = (elab_expr ctx.ctx_vararg loc env a) in
{ sdesc = Sdo a; sloc = elab_loc loc },env
(* 6.8.1 Labeled statements *)
@@ -2250,7 +2268,7 @@ let rec elab_stmt env ctx s =
{ sdesc = Slabeled(Slabel lbl, s1); sloc = elab_loc loc },env
| CASE(a, s1, loc) ->
- let a',env = elab_expr loc env a in
+ let a',env = elab_expr ctx.ctx_vararg loc env a in
begin match Ceval.integer_expr env a' with
| None ->
error loc "argument of 'case' must be an integer compile-time constant"
@@ -2271,7 +2289,7 @@ let rec elab_stmt env ctx s =
(* 6.8.4 Conditional statements *)
| If(a, s1, s2, loc) ->
- let a',env = elab_expr loc env a in
+ let a',env = elab_expr ctx.ctx_vararg loc env a in
if not (is_scalar_type env a'.etyp) then
error loc "the condition of 'if' does not have scalar type";
let s1',env = elab_stmt env ctx s1 in
@@ -2285,7 +2303,7 @@ let rec elab_stmt env ctx s =
(* 6.8.5 Iterative statements *)
| WHILE(a, s1, loc) ->
- let a',env = elab_expr loc env a in
+ let a',env = elab_expr ctx.ctx_vararg loc env a in
if not (is_scalar_type env a'.etyp) then
error loc "the condition of 'while' does not have scalar type";
let s1',env = elab_stmt env (ctx_loop ctx) s1 in
@@ -2293,7 +2311,7 @@ let rec elab_stmt env ctx s =
| DOWHILE(a, s1, loc) ->
let s1',env = elab_stmt env (ctx_loop ctx) s1 in
- let a',env = elab_expr loc env a in
+ let a',env = elab_expr ctx.ctx_vararg loc env a in
if not (is_scalar_type env a'.etyp) then
error loc "the condition of 'while' does not have scalar type";
{ sdesc = Sdowhile(s1', a'); sloc = elab_loc loc },env
@@ -2302,10 +2320,10 @@ let rec elab_stmt env ctx s =
let (a1', env', decls') =
match fc with
| Some (FC_EXP a1) ->
- let a1,env = elab_for_expr loc env (Some a1) in
+ let a1,env = elab_for_expr ctx.ctx_vararg loc env (Some a1) in
(a1, env, None)
| None ->
- let a1,env = elab_for_expr loc env None in
+ let a1,env = elab_for_expr ctx.ctx_vararg loc env None in
(a1, env, None)
| Some (FC_DECL def) ->
let (dcl, env') = elab_definition true (Env.new_scope env) def in
@@ -2315,11 +2333,11 @@ let rec elab_stmt env ctx s =
let a2',env =
match a2 with
| None -> intconst 1L IInt,env
- | Some a2 -> elab_expr loc env' a2
+ | Some a2 -> elab_expr ctx.ctx_vararg loc env' a2
in
if not (is_scalar_type env' a2'.etyp) then
error loc "the condition of 'for' does not have scalar type";
- let a3',env' = elab_for_expr loc env' a3 in
+ let a3',env' = elab_for_expr ctx.ctx_vararg loc env' a3 in
let s1',env' = elab_stmt env' (ctx_loop ctx) s1 in
let sfor = { sdesc = Sfor(a1', a2', a3', s1'); sloc = elab_loc loc } in
begin match decls' with
@@ -2329,7 +2347,7 @@ let rec elab_stmt env ctx s =
(* 6.8.4 Switch statement *)
| SWITCH(a, s1, loc) ->
- let a',env = elab_expr loc env a in
+ let a',env = elab_expr ctx.ctx_vararg loc env a in
if not (is_integer_type env a'.etyp) then
error loc "the argument of 'switch' is not an integer";
let s1',env = elab_stmt env (ctx_switch ctx) s1 in
@@ -2347,7 +2365,7 @@ let rec elab_stmt env ctx s =
(* 6.8.6 Return statements *)
| RETURN(a, loc) ->
- let a',env = elab_opt_expr loc env a in
+ let a',env = elab_opt_expr ctx.ctx_vararg loc env a in
begin match (unroll env ctx.ctx_return_typ, a') with
| TVoid _, None -> ()
| TVoid _, Some _ ->
@@ -2388,8 +2406,8 @@ let rec elab_stmt env ctx s =
| ASM(cv_specs, wide, chars, outputs, inputs, flags, loc) ->
let a = elab_cvspecs env cv_specs in
let s = elab_simple_string loc wide chars in
- let outputs,env = mmap (elab_asm_operand loc) env outputs in
- let inputs ,env= mmap (elab_asm_operand loc) env inputs in
+ let outputs,env = mmap (elab_asm_operand ctx.ctx_vararg loc) env outputs in
+ let inputs ,env= mmap (elab_asm_operand ctx.ctx_vararg loc) env inputs in
let flags = List.map (fun (w,c) -> elab_simple_string loc w c) flags in
{ sdesc = Sasm(a, s, outputs, inputs, flags);
sloc = elab_loc loc },env
@@ -2422,12 +2440,13 @@ and elab_block_body env ctx sl =
(* Elaboration of a function body. Return the corresponding C statement. *)
-let elab_funbody return_typ env b =
+let elab_funbody return_typ vararg env b =
let ctx =
{ ctx_return_typ = return_typ;
ctx_labels = stmt_labels b;
ctx_break = false;
- ctx_continue = false } in
+ ctx_continue = false;
+ ctx_vararg = vararg;} in
fst(elab_stmt env ctx b)
(* Filling in forward declaration *)