From 7ba8259eedba5e4fc25a22444a3dd92a0fcf4a82 Mon Sep 17 00:00:00 2001
From: Virgile Prevosto <virgile.prevosto@m4x.org>
Date: Tue, 3 Mar 2020 19:26:35 +0100
Subject: [PATCH] [constfold] more aggressive constfolding in dead branches of
 global initializer

otherwise, we might end up with an improper crash of cabs2cil
---
 src/kernel_internals/typing/cabs2cil.ml         | 6 ++++--
 tests/syntax/compile_constant.c                 | 2 ++
 tests/syntax/oracle/compile_constant.res.oracle | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml
index fae93b76c43..481fde16c7e 100644
--- a/src/kernel_internals/typing/cabs2cil.ml
+++ b/src/kernel_internals/typing/cabs2cil.ml
@@ -7216,7 +7216,7 @@ and doExp local_env
                we won't evaluate it. Hence, it can contain
                non-const constructions *)
             let asconst =
-              if is_true_cond = `CFalse then CNoConst else asconst
+              if is_true_cond = `CFalse then CMayConst else asconst
             in
             let r2, se2, e2', t2 =
               doExp (no_paren_local_env local_env) asconst e2 what'
@@ -7224,18 +7224,20 @@ and doExp local_env
             r2, se2, Some e2', t2
         in
         (* Do e3 for real. See above for the value of asconst *)
-        let asconst' = if is_true_cond = `CTrue then CNoConst else asconst in
+        let asconst' = if is_true_cond = `CTrue then CMayConst else asconst in
         let r3, se3, e3', t3 =
           doExp (no_paren_local_env local_env) asconst' e3 what'
         in
         let tresult = conditionalConversion t2 t3 in
         if asconst <> CNoConst && is_true_cond = `CTrue then begin
           clean_up_chunk_locals se2;
+          clean_up_chunk_locals se3;
           let loc = e2.expr_loc in
           let e2' = match e2'o with None -> Cil.one ~loc | Some e -> e in
           let _,e2' = castTo t2 tresult e2' in
           finishExp [] empty e2' tresult;
         end else if asconst <> CNoConst && is_true_cond = `CFalse then begin
+          clean_up_chunk_locals se2;
           clean_up_chunk_locals se3;
           let _,e3' = castTo t3 tresult e3' in
           finishExp [] empty e3' tresult
diff --git a/tests/syntax/compile_constant.c b/tests/syntax/compile_constant.c
index c72ac927b6e..7dcef8ed9d0 100644
--- a/tests/syntax/compile_constant.c
+++ b/tests/syntax/compile_constant.c
@@ -10,6 +10,8 @@ char test_ge = { ((-1.) >= 0.) ? 1. : 2. };
 char test_cast[] = { 1 >= (0?1U:(-1)) ? 1. : 2.,
                    ((double)1) >= (0?1U:(-1)) ? 1. : 2. };
 
+double a = 2 >= 5 ? 5 ? (long)0 || 0 ? 0. >= 0 ?: 0 : 2 : 5 : 0;
+
 extern int f(void);
 
 /* no call should be evaluated. */
diff --git a/tests/syntax/oracle/compile_constant.res.oracle b/tests/syntax/oracle/compile_constant.res.oracle
index b9baaf82b3c..b979c0f88dc 100644
--- a/tests/syntax/oracle/compile_constant.res.oracle
+++ b/tests/syntax/oracle/compile_constant.res.oracle
@@ -4,5 +4,6 @@ char pixels[3] = {(char)0.0, (char)0.0, (char)1.0};
 char test_neg = (char)2.;
 char test_ge = (char)2.;
 char test_cast[2] = {(char)2., (char)2.};
+double a = (double)0;
 char no_call[2] = {(char)1, (char)2};
 
-- 
GitLab