Skip to content

Commit a7cf7e4

Browse files
committed
Rewrite C11 generic Cabs2cil to resolve generic switch
1 parent 0067d37 commit a7cf7e4

File tree

1 file changed

+26
-24
lines changed

1 file changed

+26
-24
lines changed

src/frontc/cabs2cil.ml

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,7 +2461,7 @@ let rec doSpecList (suggestedAnonName: string) (* This string will be part of
24612461
| [A.Tfloat128] -> TFloat(FLongDouble, []) (* TODO: Correct? *)
24622462

24632463
(* Now the other type specifiers *)
2464-
(* | [A.Tdefault] -> TDefault *)
2464+
| [A.Tdefault] -> E.s (error "Default outside generic associations")
24652465
| [A.Tnamed n] -> begin
24662466
if n = "__builtin_va_list" &&
24672467
!Machdep.theMachine.Machdep.__builtin_va_list then begin
@@ -4848,31 +4848,33 @@ and doExp (asconst: bool) (* This expression is used as a constant *)
48484848

48494849
| A.EXPR_PATTERN _ -> E.s (E.bug "EXPR_PATTERN in cabs2cil input")
48504850

4851-
| A.GENERIC (expr, lst) ->
4852-
let get_exp (_, e, _) = e in
4853-
let exp = get_exp (doExp false (stripParenLocal expr) (AExp None)) in
4854-
let cil_list =
4855-
let rec make_cil_list cabs_l cil_l = match cabs_l with
4856-
| [] -> cil_l
4857-
| (s, e) :: rest -> make_cil_list rest (((doOnlyType s JUSTBASE),get_exp (doExp false (stripParenLocal e) (AExp None))) :: cil_l)
4858-
in
4859-
make_cil_list lst []
4851+
| A.GENERIC (e, al) ->
4852+
let is_default = function
4853+
| [SpecType Tdefault] -> true (* exactly matches cparser *)
4854+
| _ -> false
48604855
in
4861-
let exp_typ = typeOf exp in
4862-
let default_typ = ref voidType in
4863-
let typ =
4864-
let rec get_typ lst = match lst with
4865-
(* | (TDefault, e) :: rest -> default_typ := typeOf e; get_typ rest *)
4866-
| (t, e) :: rest -> if t = exp_typ then typeOf e else get_typ rest
4867-
| [] ->
4868-
if !default_typ = voidType then
4869-
E.s(error "Controlling expression of generic selection is not compatible with any association")
4870-
else !default_typ
4871-
in
4872-
get_typ cil_list
4856+
let (al_default, al_nondefault) = List.partition (fun (at, _) -> is_default at) al in
4857+
4858+
let typ_compatible t1 t2 =
4859+
match combineTypes CombineOther t1 t2 with (* combineTypes seems to do "compatible types" check *)
4860+
| _ -> true
4861+
| exception (Failure _) -> false
48734862
in
4874-
(* finishExp empty (Generic(exp, (cil_list))) typ *)
4875-
failwith "TODO"
4863+
let (_, _, e_typ) = doExp false (stripParenLocal e) (AExp None) in (* TODO: why stripParenLocal? *)
4864+
let al_compatible = List.filter (fun (at, _) -> typ_compatible e_typ (doOnlyType at JUSTBASE)) al_nondefault in
4865+
4866+
(* TODO: error when multiple compatible associations or defaults even when unused? *)
4867+
4868+
begin match al_compatible with
4869+
| [(_, ae)] -> doExp false (stripParenLocal ae) (AExp None) (* TODO: why stripParenLocal? *)
4870+
| [] ->
4871+
begin match al_default with
4872+
| [(_, ae)] -> doExp false (stripParenLocal ae) (AExp None) (* TODO: why stripParenLocal? *)
4873+
| [] -> E.s (error "No compatible associations or default in generic")
4874+
| _ -> E.s (error "Multiple defaults in generic")
4875+
end
4876+
| _ -> E.s (error "Multiple compatible associations in generic")
4877+
end
48764878

48774879
with e when continueOnError -> begin
48784880
(*ignore (E.log "error in doExp (%s)" (Printexc.to_string e));*)

0 commit comments

Comments
 (0)