Skip to content

Commit

Permalink
[uninit] Revise translation of conditional expression for C struct
Browse files Browse the repository at this point in the history
Summary:
This diff revises the translation of the conditional expression for C struct.

```
struct S = {
  int f1;
  int f2;
}

struct S foo(int b) {
  ...
  return b ? x : y;
}
```

Before this diff, the return statements were translated to

```
n$0 = *&__return_param;
...
*n$0 = x; // at the true branch
...
*n$0 = y; // at the false branch
```

However, this is incorrect because there is no first-value for C struct in SIL.

By this diff, it is translated to multiple instructions that copy each field separately.

```
n$0 = *&__return_param;
...
n$1 =  *&x.f1; // at the true branch
*n$0.f1 = n$1;
n$2 =  *&x.f2;
*n$0.f2 = n$2;
...
n$3 =  *&y.f1; // at the false branch
*n$0.f1 = n$3;
n$4 =  *&y.f2;
*n$0.f2 = n$4;
```

Reviewed By: jvillard

Differential Revision: D49829058

fbshipit-source-id: 3b9dd95d82e0d4e37c709126117ef7c5a130c3d7
  • Loading branch information
skcho authored and facebook-github-bot committed Oct 3, 2023
1 parent f6ea606 commit 8205df2
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
7 changes: 6 additions & 1 deletion infer/src/clang/cTrans.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,12 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
exp
in
let set_temp_var =
[Sil.Store {e1= exp_to_init; typ= var_typ; e2= init_exp; loc= sil_loc}]
match var_typ with
| {Typ.desc= Tstruct struct_name} ->
CStructUtils.struct_copy context.CContext.tenv sil_loc exp_to_init init_exp
~typ:var_typ ~struct_name
| _ ->
[Sil.Store {e1= exp_to_init; typ= var_typ; e2= init_exp; loc= sil_loc}]
in
let return = (exp_to_init, var_typ) in
let tmp_var_res_trans =
Expand Down
13 changes: 13 additions & 0 deletions infer/tests/codetoanalyze/c/pulse/uninit.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,16 @@ void FP_uninit_var_not_read_interproc_ok() {
int range_var;
check_range_wrapper(range_var_valid, &range_var);
}

struct uninit_s global_uninit_s1;

struct uninit_s global_uninit_s2;

struct uninit_s init_by_conditional_exp(int b) {
return b ? global_uninit_s1 : global_uninit_s2;
}

int call_init_by_conditionaql_exp_ok(int b) {
struct uninit_s x = init_by_conditional_exp(b);
return x.f1;
}

0 comments on commit 8205df2

Please sign in to comment.