On Fri, Oct 15, 2010 at 11:04:13AM +0200, Gabriel Kerneis wrote:
> After some discussion off-list with Elnatan, I just commited an updated
> version of his patches.

You will also find attached an updated version of the "Question" patch
(which introduces a constructor to represent the ternary operator ?:).
As said earlier, it will not be applied upstream because it impacts the
AST (and thus every existing code) but interested people should feel
free to apply it (I plan to maintain it for use in my own project).

Best regards,
-- 
Gabriel Kerneis
>From e83854c64216ce3a3d7443173d2d30ce108e0b9c Mon Sep 17 00:00:00 2001
From: Gabriel Kerneis <kern...@pps.jussieu.fr>
Date: Thu, 14 Oct 2010 16:17:24 +0200
Subject: [PATCH] Introduce a Question variant for the Cil.exp type

Thanks to Elnatan Reisner.
---
 src/check.ml            |   11 +++++++++++
 src/cil.ml              |   24 ++++++++++++++++++++++--
 src/cil.mli             |    3 +++
 src/ciloptions.ml       |    4 ++--
 src/ext/predabst.ml     |    5 +++++
 src/ext/pta/ptranal.ml  |    1 +
 src/ext/simplify.ml     |    2 ++
 src/frontc/cabs2cil.ml  |   10 +++++++++-
 test/small1/question3.c |   12 ++++++++++++
 test/testcil.pl         |    1 +
 10 files changed, 68 insertions(+), 5 deletions(-)
 create mode 100644 test/small1/question3.c

diff --git a/src/check.ml b/src/check.ml
index cadd2e7..b191dfd 100644
--- a/src/check.ml
+++ b/src/check.ml
@@ -545,6 +545,17 @@ and checkExp (isconst: bool) (e: exp) : typ =
               typeMatch tres intType;
               tres
       end
+
+      | Question (e1, e2, e3, tres) -> begin
+          let t1 = checkExp isconst e1 in
+          let t2 = checkExp isconst e2 in
+          let t3 = checkExp isconst e3 in
+          checkScalarType t1;
+          typeMatch t2 t3;
+          typeMatch t2 tres;
+          tres
+      end
+
       | AddrOf (lv) -> begin
           let tlv = checkLval isconst true lv in
           (* Only certain types can be in AddrOf *)
diff --git a/src/cil.ml b/src/cil.ml
index a7f2969..b9e0791 100644
--- a/src/cil.ml
+++ b/src/cil.ml
@@ -488,6 +488,9 @@ and exp =
                                             type of the result. The arithemtic
                                             conversions are made  explicit
                                             for the arguments *)
+  | Question   of exp * exp * exp * typ
+                                        (** (a ? b : c) operation. Includes
+                                            the type of the result *)
   | CastE      of typ * exp            (** Use {!Cil.mkCast} to make casts *)
 
   | AddrOf     of lval                 (** Always use {!Cil.mkAddrOf} to 
@@ -1748,6 +1751,7 @@ let bitwiseLevel = 75
 let questionLevel = 100
 let getParenthLevel (e: exp) = 
   match e with 
+  | Question _ -> questionLevel
   | BinOp((LAnd | LOr), _,_,_) -> 80
                                         (* Bit operations. *)
   | BinOp((BOr|BXor|BAnd),_,_,_) -> bitwiseLevel (* 75 *)
@@ -1863,8 +1867,9 @@ let rec typeOf (e: exp) : typ =
   | Lval(lv) -> typeOfLval lv
   | SizeOf _ | SizeOfE _ | SizeOfStr _ -> !typeOfSizeOf
   | AlignOf _ | AlignOfE _ -> !typeOfSizeOf
-  | UnOp (_, _, t) -> t
-  | BinOp (_, _, _, t) -> t
+  | UnOp (_, _, t)
+  | BinOp (_, _, _, t)
+  | Question (_, _, _, t)
   | CastE (t, _) -> t
   | AddrOf (lv) -> TPtr(typeOfLval lv, [])
   | StartOf (lv) -> begin
@@ -3271,6 +3276,13 @@ class defaultCilPrinterClass : cilPrinter = object (self)
           ++ (self#pExpPrec level () e2)
           ++ unalign
 
+    | Question(e1,e2,e3,_) -> 
+        (self#pExpPrec level () e1)
+          ++ text " ? "
+          ++ (self#pExpPrec level () e2)
+          ++ text " : "
+          ++ (self#pExpPrec level () e3)
+
     | CastE(t,e) -> 
         text "(" 
           ++ self#pType None () t
@@ -4596,6 +4608,10 @@ class plainCilPrinterClass =
       dprintf "%a(@[%a,@?...@])" d_plainbinop b
         self#pExp e1 self#pExp e2
 
+  | Question(e1,e2,e3,_) -> 
+      dprintf "Question(@[%a,@?%a,@?...@])"
+        self#pExp e1 self#pExp e2 self#pExp e3
+
   | SizeOf (t) -> 
       text "sizeof(" ++ self#pType None () t ++ chr ')'
   | SizeOfE (e) -> 
@@ -5094,6 +5110,9 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp =
   | BinOp (bo, e1, e2, t) -> 
       let e1' = vExp e1 in let e2' = vExp e2 in let t' = vTyp t in
       if e1' != e1 || e2' != e2 || t' != t then BinOp(bo, e1',e2',t') else e
+  | Question (e1, e2, e3, t) -> 
+      let e1' = vExp e1 in let e2' = vExp e2 in let e3' = vExp e3 in let t' = vTyp t in
+      if e1' != e1 || e2' != e2 || e3' != e3 || t' != t then Question(e1',e2',e3',t') else e
   | CastE (t, e1) ->           
       let t' = vTyp t in let e1' = vExp e1 in
       if t' != t || e1' != e1 then CastE(t', e1') else e
@@ -5982,6 +6001,7 @@ let rec isConstant = function
   | Const _ -> true
   | UnOp (_, e, _) -> isConstant e
   | BinOp (_, e1, e2, _) -> isConstant e1 && isConstant e2
+  | Question (e1, e2, e3, _) -> isConstant e1 && isConstant e2 && isConstant e3
   | Lval (Var vi, NoOffset) -> 
       (vi.vglob && isArrayType vi.vtype || isFunctionType vi.vtype)
   | Lval _ -> false
diff --git a/src/cil.mli b/src/cil.mli
index dc817df..ba5b441 100644
--- a/src/cil.mli
+++ b/src/cil.mli
@@ -594,6 +594,9 @@ and exp =
     (** Binary operation. Includes the type of the result. The arithmetic 
      * conversions are made explicit for the arguments. *)
 
+  | Question   of exp * exp * exp * typ
+    (** (a ? b : c) operation. Includes the type of the result *)
+
   | CastE      of typ * exp            
     (** Use {!Cil.mkCast} to make casts.  *)
 
diff --git a/src/ciloptions.ml b/src/ciloptions.ml
index acd5c3d..641692d 100644
--- a/src/ciloptions.ml
+++ b/src/ciloptions.ml
@@ -295,12 +295,12 @@ let options : (string * Arg.spec * string) list =
     "--useLogicalOperators",
     Arg.Set Cil.useLogicalOperators,
     (" Where possible (that is, if there are no side-effects),\n\t\t\t\t" ^
-       "retain && and || (instead of transforming them to If statements)" ^
+       "retain &&, || and ?: (instead of transforming them to If statements)" ^
        is_default !Cil.useLogicalOperators);
 
     "--noUseLogicalOperators",
     Arg.Clear Cil.useLogicalOperators,
-     ("Transform && and || to If statements" ^
+     ("Transform &&, || and ?: to If statements" ^
        is_default (not !Cil.useLogicalOperators));
 
     "--keepunused",
diff --git a/src/ext/predabst.ml b/src/ext/predabst.ml
index cfb7edc..6be2832 100644
--- a/src/ext/predabst.ml
+++ b/src/ext/predabst.ml
@@ -207,6 +207,11 @@ module Solver = functor(T:TRANSLATOR) ->
 	  let e1 = transExp e1 in
 	  let e2 = transExp e2 in
 	  transBinOp op e1 e2
+      | Question (e1,e2,e3,_) ->
+	  let e1 = transExp e1 in
+	  let e2 = transExp e2 in
+	  let e3 = transExp e3 in
+	  T.mkIte e1 e2 e3
       | SizeOf typ -> T.mkConst ((bitsSizeOf typ)/8)
       | SizeOfE e -> transExp (SizeOf(typeOf e))
       | SizeOfStr s -> T.mkConst (1 + String.length s)
diff --git a/src/ext/pta/ptranal.ml b/src/ext/pta/ptranal.ml
index 5a0ee20..3312d6a 100644
--- a/src/ext/pta/ptranal.ml
+++ b/src/ext/pta/ptranal.ml
@@ -244,6 +244,7 @@ and analyze_expr (e : exp ) : A.tau =
       | AlignOf _ -> A.bottom ()
       | UnOp (op, e, t) -> analyze_expr e
       | BinOp (op, e, e', t) -> A.join (analyze_expr e) (analyze_expr e')
+      | Question (_, e, e', _) -> A.join (analyze_expr e) (analyze_expr e')
       | CastE (t, e) -> analyze_expr e
       | AddrOf l ->
           if !fun_ptrs_as_funs && isFunctionType (typeOfLval l) then
diff --git a/src/ext/simplify.ml b/src/ext/simplify.ml
index 706e12d..c050724 100644
--- a/src/ext/simplify.ml
+++ b/src/ext/simplify.ml
@@ -104,6 +104,8 @@ let rec makeThreeAddress
   | Lval lv -> Lval (simplifyLval setTemp lv)
   | BinOp(bo, e1, e2, tres) -> 
       BinOp(bo, makeBasic setTemp e1, makeBasic setTemp e2, tres)
+  | Question _ ->
+      E.s (bug "Simplify: There should not be a \"?:\" operator here.")
   | UnOp(uo, e1, tres) -> 
       UnOp(uo, makeBasic setTemp e1, tres)
   | CastE(t, e) -> 
diff --git a/src/frontc/cabs2cil.ml b/src/frontc/cabs2cil.ml
index 30da2aa..a93d6f0 100644
--- a/src/frontc/cabs2cil.ml
+++ b/src/frontc/cabs2cil.ml
@@ -4385,7 +4385,15 @@ and doExp (asconst: bool)   (* This expression is used as a constant *)
              | Some e2' -> 
                  finishExp (se1 @@ se2) (snd (castTo t2 tresult e2')) tresult
            end
-
+        | CEExp (se1, e1') when !useLogicalOperators && isEmpty se2 && isEmpty se3 ->
+           let e2' = match e2'o with
+               None -> (* use e1' *)
+                 snd (castTo t2 tresult e1')
+             | Some e2' -> 
+                 snd (castTo t2 tresult e2')
+           in
+           let e3' = snd (castTo t3 tresult e3') in
+           finishExp se1 (Question (e1', e2', e3', tresult)) tresult
         | _ -> (* Use a conditional *) begin
             match e2'o with 
               None -> (* has form "e1 ? : e3"  *)
diff --git a/test/small1/question3.c b/test/small1/question3.c
new file mode 100644
index 0000000..be406a0
--- /dev/null
+++ b/test/small1/question3.c
@@ -0,0 +1,12 @@
+int main() {
+  int x, y, z;
+  int keep1   = x ? y : z;
+  int unfold1 = x ? y : z++;
+  int unfold2 = x ? y++ : z;
+  int unfold3 = x ? y++ : z++;
+  int keep2   = x++ ? y : z;
+  int unfold4 = x++ ? y : z++;
+  int unfold5 = x++ ? y++ : z;
+  int unfold6 = x++ ? y++ : z++;
+  return 0;
+}
diff --git a/test/testcil.pl b/test/testcil.pl
index 0763881..6b79467 100644
--- a/test/testcil.pl
+++ b/test/testcil.pl
@@ -209,6 +209,7 @@ addTest("testrun/offsetof2");
 addTest("testrun/offsetof3");
 addTest("testrun/question");
 addTest("testrun/question2");
+addTest("testrun/question3 USE_LOGICAL_OPERATORS=1");
 addTest("test/argcast");
 addBadComment("test/argcast", 
 	      "Notbug. CIL bases type for implicit functions based on first call's argument.");
-- 
1.7.1

------------------------------------------------------------------------------
Download new Adobe(R) Flash(R) Builder(TM) 4
The new Adobe(R) Flex(R) 4 and Flash(R) Builder(TM) 4 (formerly 
Flex(R) Builder(TM)) enable the development of rich applications that run
across multiple browsers and platforms. Download your free trials today!
http://p.sf.net/sfu/adobe-dev2dev
_______________________________________________
CIL-users mailing list
CIL-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cil-users

Reply via email to