diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index d84ef9c95..de302d308 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -917,7 +917,7 @@ struct res_state and compoundStmt_trans trans_state stmt_info stmt_list = - instructions trans_state (IList.rev stmt_list) + instructions trans_state stmt_list and conditionalOperator_trans trans_state stmt_info stmt_list expr_info = let context = trans_state.context in @@ -2057,8 +2057,8 @@ struct { root_nodes = res_trans_tail.root_nodes; leaf_nodes = []; ids = res_trans_s.ids @ res_trans_tail.ids; - instrs = res_trans_s.instrs @ res_trans_tail.instrs; - exps = res_trans_s.exps @ res_trans_tail.exps } + instrs = res_trans_tail.instrs @ res_trans_s.instrs; + exps = res_trans_tail.exps @ res_trans_s.exps } and get_clang_stmt_trans stmt_list = let instruction' = fun stmt -> fun trans_state -> instruction trans_state stmt in @@ -2073,7 +2073,8 @@ struct (** Given a translation state, this function translates a list of clang statements. *) and instructions trans_state stmt_list = - exec_trans_instrs trans_state (get_clang_stmt_trans stmt_list) + let rev_stmt_list = IList.rev stmt_list in + exec_trans_instrs trans_state (get_clang_stmt_trans rev_stmt_list) and expression_trans context stmt warning = let trans_state = { diff --git a/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c b/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c index 1389c4061..34e91c35d 100644 --- a/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c +++ b/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c @@ -13,3 +13,11 @@ int main() { y = ({int X = 4; X;}); return 0; } + +int test(int* p) { + return ({ + int x = *p; + int y = 1; + x + y; + }); +} diff --git a/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c.dot b/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c.dot index 2a60498a6..4e9486678 100644 --- a/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c.dot +++ b/infer/tests/codetoanalyze/c/frontend/nestedoperators/gnuexpr.c.dot @@ -1,9 +1,20 @@ digraph iCFG { +8 [label="8: Return Stmt \n n$2=*&p:int * [line 19]\n n$3=*n$2:int [line 19]\n *&x:int =n$3 [line 19]\n *&y:int =1 [line 20]\n n$0=*&x:int [line 21]\n n$1=*&y:int [line 21]\n n$4=*(n$0 + n$1):int [line 18]\n *&return:int =n$4 [line 18]\n REMOVE_TEMPS(n$4,n$0,n$1,n$2,n$3); [line 18]\n NULLIFY(&p,false); [line 18]\n NULLIFY(&x,false); [line 18]\n NULLIFY(&y,false); [line 18]\n APPLY_ABSTRACTION; [line 18]\n " shape="box"] + + + 8 -> 7 ; +7 [label="7: Exit test \n " color=yellow style=filled] + + +6 [label="6: Start test\nFormals: p:int *\nLocals: y:int x:int \n DECLARE_LOCALS(&return,&y,&x); [line 17]\n NULLIFY(&x,false); [line 17]\n NULLIFY(&y,false); [line 17]\n " color=yellow style=filled] + + + 6 -> 8 ; 5 [label="5: DeclStmt \n *&y:int =3 [line 11]\n NULLIFY(&y,false); [line 11]\n " shape="box"] 5 -> 4 ; -4 [label="4: BinaryOperatorStmt: Assign \n n$0=*&X:int [line 13]\n *&X:int =4 [line 13]\n n$1=*&X:int [line 13]\n *&y:int =n$1 [line 13]\n REMOVE_TEMPS(n$1,n$0); [line 13]\n NULLIFY(&X,false); [line 13]\n NULLIFY(&y,false); [line 13]\n " shape="box"] +4 [label="4: BinaryOperatorStmt: Assign \n *&X:int =4 [line 13]\n n$0=*&X:int [line 13]\n n$1=*n$0:int [line 13]\n *&y:int =n$1 [line 13]\n REMOVE_TEMPS(n$1,n$0); [line 13]\n NULLIFY(&X,false); [line 13]\n NULLIFY(&y,false); [line 13]\n " shape="box"] 4 -> 3 ; @@ -14,7 +25,7 @@ digraph iCFG { 2 [label="2: Exit main \n " color=yellow style=filled] -1 [label="1: Start main\nFormals: \nLocals: X:int y:int \n DECLARE_LOCALS(&return,&X,&y); [line 10]\n NULLIFY(&y,false); [line 10]\n " color=yellow style=filled] +1 [label="1: Start main\nFormals: \nLocals: X:int y:int \n DECLARE_LOCALS(&return,&X,&y); [line 10]\n NULLIFY(&X,false); [line 10]\n NULLIFY(&y,false); [line 10]\n " color=yellow style=filled] 1 -> 5 ; diff --git a/infer/tests/codetoanalyze/objc/frontend/block/dispatch_in_macro.m b/infer/tests/codetoanalyze/objc/frontend/block/dispatch_in_macro.m new file mode 100644 index 000000000..00789df9f --- /dev/null +++ b/infer/tests/codetoanalyze/objc/frontend/block/dispatch_in_macro.m @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + + +#define INITIALIZE_AND_RETURN_STATIC(...) ({ \ +static __typeof__(__VA_ARGS__) static_storage; \ +static dispatch_once_t once_token; \ +dispatch_once(&once_token, ^{ static_storage = (__VA_ARGS__); }); \ +static_storage; \ +}) + +id test() { + return INITIALIZE_AND_RETURN_STATIC([NSObject new]); +} diff --git a/infer/tests/endtoend/objc/DispatchInMacroTest.java b/infer/tests/endtoend/objc/DispatchInMacroTest.java new file mode 100644 index 000000000..087d970dd --- /dev/null +++ b/infer/tests/endtoend/objc/DispatchInMacroTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +package endtoend.objc; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.ResultContainsExactly.containsExactly; + +import com.google.common.collect.ImmutableList; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.InferResults; +import utils.InferRunner; + +public class DispatchInMacroTest { + + public static final String FILE = + "infer/tests/codetoanalyze/objc/frontend/block/dispatch_in_macro.m"; + + + private static ImmutableList inferCmd; + + public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE"; + + @ClassRule + public static DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createObjCInferCommand(folder, FILE); + } + + @Test + public void whenInferRunsOnAtomicProperty() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferObjC(inferCmd); + assertThat( + "Results should not contain null dereference", + inferResults, + containsExactly( + NULL_DEREFERENCE, + FILE, + new String[]{} + ) + ); + } +}