From 8f797bab845830fed3e3da7c417ff611a6efe7f1 Mon Sep 17 00:00:00 2001 From: Akos Hajdu Date: Wed, 21 Jul 2021 09:10:56 -0700 Subject: [PATCH] [erl-frontend] Support xor expressions Summary: Add support for the xor operator by reducing `(X xor Y)` to `(X and not Y) or (not X and Y)`. Alternatively, `(X != Y)` could have been used but that might not be safe since SIL models Booleans with integers. Reviewed By: skcho Differential Revision: D29816793 fbshipit-source-id: 2496b718b --- infer/src/erlang/ErlangTranslator.ml | 9 +++++++ .../codetoanalyze/erlang/features/issues.exp | 2 ++ .../erlang/features/src/logic.erl | 26 ++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/infer/src/erlang/ErlangTranslator.ml b/infer/src/erlang/ErlangTranslator.ml index c1efab9e5..12313d3d0 100644 --- a/infer/src/erlang/ErlangTranslator.ml +++ b/infer/src/erlang/ErlangTranslator.ml @@ -418,6 +418,15 @@ and translate_expression env {Ast.line; simple_expression} = make_simple_eager Mod (* TODO: check semantics of Rem vs Mod *) | Sub -> make_simple_eager (MinusA None) + | Xor -> + let expr = + Exp.BinOp + ( LOr + , Exp.BinOp (LAnd, Var id1, Exp.UnOp (LNot, Var id2, None)) + , Exp.BinOp (LAnd, Exp.UnOp (LNot, Var id1, None), Var id2) ) + in + let op_block = Block.make_load env ret_var expr any in + Block.all env [block1; block2; op_block] | todo -> L.debug Capture Verbose "@[todo ErlangTranslator.translate_expression(BinaryOperator) %s@." diff --git a/infer/tests/codetoanalyze/erlang/features/issues.exp b/infer/tests/codetoanalyze/erlang/features/issues.exp index 87c599ed9..990ba1fef 100644 --- a/infer/tests/codetoanalyze/erlang/features/issues.exp +++ b/infer/tests/codetoanalyze/erlang/features/issues.exp @@ -36,6 +36,8 @@ codetoanalyze/erlang/features/src/logic.erl, test_andalso10_Bad/0, 1, NO_TRUE_BR codetoanalyze/erlang/features/src/logic.erl, test_or00_Bad/0, 1, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [no true branch in if expression here] codetoanalyze/erlang/features/src/logic.erl, test_orelse00_Bad/0, 1, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [no true branch in if expression here] codetoanalyze/erlang/features/src/logic.erl, test_unot_Bad/0, 1, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [no true branch in if expression here] +codetoanalyze/erlang/features/src/logic.erl, test_xor00_Bad/0, 1, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [no true branch in if expression here] +codetoanalyze/erlang/features/src/logic.erl, test_xor11_Bad/0, 1, NO_TRUE_BRANCH_IN_IF, no_bucket, ERROR, [no true branch in if expression here] codetoanalyze/erlang/features/src/short_circuit.erl, accepts_one/1, 0, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [*** LATENT ***,no matching function clause here] codetoanalyze/erlang/features/src/short_circuit.erl, test_and_Bad/0, -7, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `accepts_one/1`,no matching function clause here] codetoanalyze/erlang/features/src/short_circuit.erl, test_andalso_Bad/0, -15, NO_MATCHING_FUNCTION_CLAUSE, no_bucket, ERROR, [calling context starts here,in call to `accepts_one/1`,no matching function clause here] diff --git a/infer/tests/codetoanalyze/erlang/features/src/logic.erl b/infer/tests/codetoanalyze/erlang/features/src/logic.erl index a056cbdaa..df6c0dceb 100644 --- a/infer/tests/codetoanalyze/erlang/features/src/logic.erl +++ b/infer/tests/codetoanalyze/erlang/features/src/logic.erl @@ -27,7 +27,11 @@ test_orelse10_Ok/0, test_orelse11_Ok/0, test_unot_Ok/0, - test_unot_Bad/0 + test_unot_Bad/0, + test_xor00_Bad/0, + test_xor01_Ok/0, + test_xor10_Ok/0, + test_xor11_Bad/0 ]). test_and00_Bad() -> @@ -119,3 +123,23 @@ test_unot_Bad() -> if not ?T -> ok end. + +test_xor00_Bad() -> + if + ?F xor ?F -> ok + end. + +test_xor01_Ok() -> + if + ?F xor ?T -> ok + end. + +test_xor10_Ok() -> + if + ?T xor ?F -> ok + end. + +test_xor11_Bad() -> + if + ?T xor ?T -> ok + end.