[clang] Fix translation of fast loops

master
Dulma Rodriguez 10 years ago
parent bec5bafc72
commit d3f20dcaca

@ -147,10 +147,16 @@ let make_decl_ref_exp stmt_info expr_info drei =
} in
DeclRefExpr(stmt_info, [], expr_info, drei)
let make_obj_c_message_expr_info sel typ =
let make_obj_c_message_expr_info_instance sel =
{
Clang_ast_t.omei_selector = sel;
Clang_ast_t.omei_receiver_kind = `Class (create_qual_type typ)
Clang_ast_t.omei_receiver_kind = `Instance
}
let make_obj_c_message_expr_info_class selector qt =
{
omei_selector = selector;
omei_receiver_kind = `Class (create_qual_type qt);
}
let make_general_decl_ref k name is_hidden qt = {
@ -181,17 +187,6 @@ let make_obj_c_ivar_ref_expr_info k n qt = {
Clang_ast_t.ovrei_is_free_ivar = true;
}
let make_nondet_exp stmt_info =
let drei = {
Clang_ast_t.drti_decl_ref = Some (make_decl_ref "__INFER_NON_DET");
Clang_ast_t.drti_found_decl_ref = None; } in
let qt = create_int_type () in
let ei = make_expr_info qt `Ordinary in
let e = make_decl_ref_exp stmt_info ei drei in
let cast = create_implicit_cast_expr stmt_info [e] qt `LValueToRValue in
let zero = create_integer_literal stmt_info "0" in
BinaryOperator(stmt_info, [cast; zero], ei, { Clang_ast_t.boi_kind = `GT } )
(* Build an AST cast expression of a decl_ref_expr *)
let make_cast_expr qt di decl_ref_expr_info objc_kind =
let expr_info = make_expr_info qt objc_kind in
@ -260,14 +255,14 @@ let make_decl_ref_exp_var (var_name, var_qt) var_kind stmt_info =
let expr_info = make_expr_info var_qt in
make_decl_ref_exp stmt_info expr_info (make_decl_ref_expr_info decl_ref)
let make_message_expr param_qt selector decl_ref_exp stmt_info =
let make_message_expr param_qt selector decl_ref_exp stmt_info add_cast =
let stmt_info = stmt_info_with_fresh_pointer stmt_info in
let parameters =
if add_cast then
let cast_expr = create_implicit_cast_expr stmt_info [decl_ref_exp] param_qt `LValueToRValue in
let parameters = [cast_expr] in
let obj_c_message_expr_info = {
omei_selector = selector;
omei_receiver_kind = `Instance
} in
[cast_expr]
else [decl_ref_exp] in
let obj_c_message_expr_info = make_obj_c_message_expr_info_instance selector in
let expr_info = make_expr_info param_qt in
ObjCMessageExpr (stmt_info, parameters, expr_info, obj_c_message_expr_info)
@ -279,11 +274,22 @@ let make_binary_stmt stmt1 stmt2 stmt_info expr_info boi =
let stmt_info = stmt_info_with_fresh_pointer stmt_info in
BinaryOperator(stmt_info, [stmt1; stmt2], expr_info, boi)
let make_obj_c_message_expr_info_class selector qt =
{
omei_selector = selector;
omei_receiver_kind = `Class qt;
}
let make_next_object_exp stmt_info item items =
let var_decl_ref, var_type =
match item with
| DeclStmt (stmt_info, _, [VarDecl(di, var_name, var_type, _)]) ->
let decl_ref = make_general_decl_ref `Var var_name false var_type in
let stmt_info_var = {
si_pointer = di.Clang_ast_t.di_pointer;
si_source_range = di.Clang_ast_t.di_source_range
} in
DeclRefExpr(stmt_info_var, [], (make_expr_info var_type), (make_decl_ref_expr_info decl_ref)),
var_type
| _ -> assert false in
let message_call = make_message_expr (create_qual_type CFrontend_config.id_cl)
CFrontend_config.next_object items stmt_info false in
let boi = { Clang_ast_t.boi_kind = `Assign } in
make_binary_stmt var_decl_ref message_call stmt_info (make_expr_info var_type) boi
let empty_var_decl = {
vdi_storage_class = None;

@ -37,9 +37,7 @@ val make_cast_expr : qual_type -> decl_info -> decl_ref_expr_info -> object_kind
val make_self_field : string -> decl_info -> qual_type -> string -> stmt
val make_nondet_exp : stmt_info -> stmt
val make_obj_c_message_expr_info : string -> string -> obj_c_message_expr_info
val make_next_object_exp : stmt_info -> stmt -> Clang_ast_t.stmt -> Clang_ast_t.stmt
val create_nil : stmt_info -> stmt
@ -47,7 +45,7 @@ val create_implicit_cast_expr : stmt_info -> stmt list -> qual_type -> cast_kind
val create_char_type : unit -> qual_type
val make_message_expr : qual_type -> string -> stmt -> stmt_info -> stmt
val make_message_expr : qual_type -> string -> stmt -> stmt_info -> bool -> stmt
val make_compound_stmt : stmt list -> stmt_info -> stmt
@ -55,7 +53,9 @@ val make_decl_ref_exp_var : string * qual_type -> decl_kind -> stmt_info -> stmt
val make_binary_stmt : stmt -> stmt -> stmt_info -> expr_info -> binary_operator_info -> stmt
val make_obj_c_message_expr_info_class : string -> qual_type -> obj_c_message_expr_info
val make_obj_c_message_expr_info_class : string -> string -> obj_c_message_expr_info
val make_obj_c_message_expr_info_instance : string -> obj_c_message_expr_info
val translate_dispatch_function : string -> stmt_info -> stmt list -> expr_info -> int -> stmt * qual_type

@ -19,6 +19,8 @@ let nsstring_cl = "NSString"
let nsobject_cl = "NSObject"
let next_object = "nextObject"
let nsautorelease_pool_cl = "NSAutoreleasePool"
let id_cl = "id"

@ -47,6 +47,8 @@ val nsstring_cl : string
val nsobject_cl : string
val next_object : string
val nsautorelease_pool_cl : string
val string_with_utf8_m : string

@ -605,8 +605,7 @@ struct
let fst_res_trans = instruction trans_state_param stmt in
obj_c_message_expr_info, fst_res_trans
with Self.SelfClassException class_name ->
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class selector
(Ast_expressions.create_qual_type class_name) in
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class selector class_name in
obj_c_message_expr_info, empty_res_trans) in
let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) rest in
obj_c_message_expr_info, collect_res_trans (fst_res_trans :: l)
@ -1078,9 +1077,9 @@ struct
let root_nodes, leaf_nodes = loop_instruction trans_state dowhile_kind stmt_info in
{ empty_res_trans with root_nodes = root_nodes; leaf_nodes = leaf_nodes }
and objCForCollectionStmt_trans trans_state cond body stmt_info =
let cond = Ast_expressions.make_nondet_exp stmt_info in
let while_kind = Loops.While (cond, body) in
and objCForCollectionStmt_trans trans_state item items body stmt_info =
let bin_op = Ast_expressions.make_next_object_exp stmt_info item items in
let while_kind = Loops.While (bin_op, body) in
let root_nodes, leaf_nodes = loop_instruction trans_state while_kind stmt_info in
{ empty_res_trans with root_nodes = root_nodes; leaf_nodes = leaf_nodes }
@ -1498,14 +1497,14 @@ struct
and objCBoxedExpr_trans trans_state info sel stmt_info stmts =
let typ = CTypes_decl.class_from_pointer_type trans_state.context.tenv info.Clang_ast_t.ei_qual_type in
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info sel typ in
let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class sel typ in
let message_stmt = ObjCMessageExpr(stmt_info, stmts, info, obj_c_message_expr_info) in
instruction trans_state message_stmt
and objCArrayLiteral_trans trans_state info stmt_info stmts =
let typ = CTypes_decl.class_from_pointer_type trans_state.context.tenv info.Clang_ast_t.ei_qual_type in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info CFrontend_config.array_with_objects_count_m typ in
Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.array_with_objects_count_m typ in
let stmts = stmts@[Ast_expressions.create_nil stmt_info] in
let message_stmt = ObjCMessageExpr(stmt_info, stmts, info, obj_c_message_expr_info) in
instruction trans_state message_stmt
@ -1513,7 +1512,7 @@ struct
and objCDictionaryLiteral_trans trans_state info stmt_info stmts =
let typ = CTypes_decl.class_from_pointer_type trans_state.context.tenv info.Clang_ast_t.ei_qual_type in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info CFrontend_config.dict_with_objects_and_keys_m typ in
Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.dict_with_objects_and_keys_m typ in
let stmts = swap_elements_list stmts in
let stmts = stmts@[Ast_expressions.create_nil stmt_info] in
let message_stmt = ObjCMessageExpr(stmt_info, stmts, info, obj_c_message_expr_info) in
@ -1524,7 +1523,7 @@ struct
(Ast_expressions.create_char_type ()) `ArrayToPointerDecay] in
let typ = CTypes_decl.class_from_pointer_type trans_state.context.tenv info.Clang_ast_t.ei_qual_type in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info CFrontend_config.string_with_utf8_m typ in
Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.string_with_utf8_m typ in
let message_stmt = ObjCMessageExpr(stmt_info, stmts, info, obj_c_message_expr_info) in
instruction trans_state message_stmt
@ -1667,8 +1666,8 @@ struct
| DoStmt(stmt_info, [body; cond]) ->
doStmt_trans trans_state stmt_info cond body
| ObjCForCollectionStmt(stmt_info, [item; _; body]) ->
objCForCollectionStmt_trans trans_state item body stmt_info
| ObjCForCollectionStmt(stmt_info, [item; items; body]) ->
objCForCollectionStmt_trans trans_state item items body stmt_info
| NullStmt(stmt_info, stmt_list) ->
nullStmt_trans trans_state.succ_nodes stmt_info

@ -315,15 +315,15 @@ let make_getter_setter cfg curr_class decl_info property_impl_decl_info =
let param_decl =
Ast_expressions.make_decl_ref_exp_var (param_name, qt_param) `ParmVar stmt_info in
let retain_call =
Ast_expressions.make_message_expr qt_param retain param_decl stmt_info in
Ast_expressions.make_message_expr qt_param retain param_decl stmt_info true in
let release_call =
Ast_expressions.make_message_expr qt_param release lhs_exp stmt_info in
Ast_expressions.make_message_expr qt_param release lhs_exp stmt_info true in
[retain_call; release_call; setter]
else if Ast_utils.is_copy memory_management_attribute then
let param_decl =
Ast_expressions.make_decl_ref_exp_var (param_name, qt_param) `ParmVar stmt_info in
let copy_call =
Ast_expressions.make_message_expr qt_param copy param_decl stmt_info in
Ast_expressions.make_message_expr qt_param copy param_decl stmt_info true in
let setter =
Ast_expressions.make_binary_stmt lhs_exp copy_call stmt_info expr_info boi in
[setter]

@ -1,25 +1,25 @@
digraph iCFG {
10 [label="10: DeclStmt \n n$6=_fun_NSString_stringWithUTF8String:(\"Mercedes-Benz\":char *) [line 14]\n n$7=_fun_NSString_stringWithUTF8String:(\"BMW\":char *) [line 14]\n n$8=_fun_NSString_stringWithUTF8String:(\"Porsche\":char *) [line 14]\n n$9=_fun_NSString_stringWithUTF8String:(\"Opel\":char *) [line 15]\n n$10=_fun_NSString_stringWithUTF8String:(\"Volkswagen\":char *) [line 15]\n n$11=_fun_NSString_stringWithUTF8String:(\"Audi\":char *) [line 15]\n n$5=_fun_NSArray_arrayWithObjects:count:(n$6:struct objc_object *,n$7:struct objc_object *,n$8:struct objc_object *,n$9:struct objc_object *,n$10:struct objc_object *,n$11:struct objc_object *,0:struct objc_object *) [line 14]\n *&germanCars:class NSArray *=n$5 [line 14]\n REMOVE_TEMPS(n$5,n$6,n$7,n$8,n$9,n$10,n$11); [line 14]\n " shape="box"]
10 [label="10: DeclStmt \n n$8=_fun_NSString_stringWithUTF8String:(\"Mercedes-Benz\":char *) [line 14]\n n$9=_fun_NSString_stringWithUTF8String:(\"BMW\":char *) [line 14]\n n$10=_fun_NSString_stringWithUTF8String:(\"Porsche\":char *) [line 14]\n n$11=_fun_NSString_stringWithUTF8String:(\"Opel\":char *) [line 15]\n n$12=_fun_NSString_stringWithUTF8String:(\"Volkswagen\":char *) [line 15]\n n$13=_fun_NSString_stringWithUTF8String:(\"Audi\":char *) [line 15]\n n$7=_fun_NSArray_arrayWithObjects:count:(n$8:struct objc_object *,n$9:struct objc_object *,n$10:struct objc_object *,n$11:struct objc_object *,n$12:struct objc_object *,n$13:struct objc_object *,0:struct objc_object *) [line 14]\n *&germanCars:class NSArray *=n$7 [line 14]\n REMOVE_TEMPS(n$7,n$8,n$9,n$10,n$11,n$12,n$13); [line 14]\n " shape="box"]
10 -> 9 ;
9 [label="9: BinaryOperatorStmt: Assign \n n$4=*&germanCars:class NSArray * [line 16]\n n$3=_fun_NSArray_objectAtIndexedSubscript:(n$4:class NSArray *,3:unsigned long ) virtual [line 16]\n *&s:class NSString *=n$3 [line 16]\n REMOVE_TEMPS(n$3,n$4); [line 16]\n NULLIFY(&germanCars,false); [line 16]\n NULLIFY(&s,false); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
9 [label="9: BinaryOperatorStmt: Assign \n n$6=*&germanCars:class NSArray * [line 16]\n n$5=_fun_NSArray_objectAtIndexedSubscript:(n$6:class NSArray *,3:unsigned long ) virtual [line 16]\n *&s:class NSString *=n$5 [line 16]\n REMOVE_TEMPS(n$5,n$6); [line 16]\n NULLIFY(&s,false); [line 16]\n APPLY_ABSTRACTION; [line 16]\n " shape="box"]
9 -> 4 ;
8 [label="8: Call _fun_NSLog \n n$1=_fun_NSString_stringWithUTF8String:(\"%@\":char *) [line 19]\n n$2=*&item:class NSString * [line 19]\n _fun_NSLog(n$1:struct objc_object *,n$2:class NSString *) [line 19]\n REMOVE_TEMPS(n$1,n$2); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"]
8 [label="8: Call _fun_NSLog \n n$3=_fun_NSString_stringWithUTF8String:(\"%@\":char *) [line 19]\n n$4=*&item:class NSString * [line 19]\n _fun_NSLog(n$3:struct objc_object *,n$4:class NSString *) [line 19]\n REMOVE_TEMPS(n$3,n$4); [line 19]\n NULLIFY(&item,false); [line 19]\n APPLY_ABSTRACTION; [line 19]\n " shape="box"]
8 -> 4 ;
7 [label="7: Prune (false branch) \n PRUNE(((n$0 > 0) == 0), false); [line 18]\n REMOVE_TEMPS(n$0); [line 18]\n " shape="invhouse"]
7 [label="7: Prune (false branch) \n PRUNE((n$2 == 0), false); [line 18]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 18]\n " shape="invhouse"]
7 -> 3 ;
6 [label="6: Prune (true branch) \n PRUNE(((n$0 > 0) != 0), true); [line 18]\n REMOVE_TEMPS(n$0); [line 18]\n " shape="invhouse"]
6 [label="6: Prune (true branch) \n PRUNE((n$2 != 0), true); [line 18]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 18]\n " shape="invhouse"]
6 -> 8 ;
5 [label="5: BinaryOperatorStmt: GT \n n$0=*&__INFER_NON_DET:int [line 18]\n " shape="box"]
5 [label="5: BinaryOperatorStmt: Assign \n n$1=*&germanCars:class NSArray * [line 18]\n n$0=_fun_NSArray_nextObject(n$1:class NSArray *) virtual [line 18]\n *&item:class NSString *=n$0 [line 18]\n n$2=*&item:class NSString * [line 18]\n " shape="box"]
5 -> 6 ;
@ -28,14 +28,14 @@ digraph iCFG {
4 -> 5 ;
3 [label="3: Return Stmt \n NULLIFY(&item,false); [line 22]\n *&return:int =0 [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"]
3 [label="3: Return Stmt \n NULLIFY(&germanCars,false); [line 22]\n NULLIFY(&item,false); [line 22]\n *&return:int =0 [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit main \n " color=yellow style=filled]
1 [label="1: Start main\nFormals: \nLocals: s:class NSString * germanCars:class NSArray * item:class NSString * \n DECLARE_LOCALS(&return,&s,&germanCars,&item); [line 10]\n NULLIFY(&germanCars,false); [line 10]\n NULLIFY(&s,false); [line 10]\n " color=yellow style=filled]
1 [label="1: Start main\nFormals: \nLocals: s:class NSString * germanCars:class NSArray * item:class NSString * \n DECLARE_LOCALS(&return,&s,&germanCars,&item); [line 10]\n NULLIFY(&germanCars,false); [line 10]\n NULLIFY(&item,false); [line 10]\n NULLIFY(&s,false); [line 10]\n " color=yellow style=filled]
1 -> 10 ;

@ -0,0 +1,78 @@
digraph iCFG {
19 [label="19: DeclStmt \n *&size:int =0 [line 17]\n " shape="box"]
19 -> 18 ;
18 [label="18: DeclStmt \n *&item:class NSArray *=0 [line 18]\n NULLIFY(&item,false); [line 18]\n APPLY_ABSTRACTION; [line 18]\n " shape="box"]
18 -> 13 ;
17 [label="17: ComppoundAssignStmt \n n$12=*&item:class NSArray * [line 20]\n n$11=_fun_NSArray_count(n$12:class NSArray *) virtual [line 20]\n n$13=*&size:int [line 20]\n *&size:int =(n$13 + n$11) [line 20]\n REMOVE_TEMPS(n$11,n$12,n$13); [line 20]\n NULLIFY(&item,false); [line 20]\n APPLY_ABSTRACTION; [line 20]\n " shape="box"]
17 -> 13 ;
16 [label="16: Prune (false branch) \n PRUNE((n$10 == 0), false); [line 19]\n REMOVE_TEMPS(n$8,n$9,n$10); [line 19]\n " shape="invhouse"]
16 -> 12 ;
15 [label="15: Prune (true branch) \n PRUNE((n$10 != 0), true); [line 19]\n REMOVE_TEMPS(n$8,n$9,n$10); [line 19]\n " shape="invhouse"]
15 -> 17 ;
14 [label="14: BinaryOperatorStmt: Assign \n n$9=*&items:class NSArray * [line 19]\n n$8=_fun_NSArray_nextObject(n$9:class NSArray *) virtual [line 19]\n *&item:class NSArray *=n$8 [line 19]\n n$10=*&item:class NSArray * [line 19]\n " shape="box"]
14 -> 15 ;
14 -> 16 ;
13 [label="13: + \n " ]
13 -> 14 ;
12 [label="12: Return Stmt \n NULLIFY(&item,false); [line 22]\n NULLIFY(&items,false); [line 22]\n n$7=*&size:int [line 22]\n *&return:int =n$7 [line 22]\n REMOVE_TEMPS(n$7); [line 22]\n NULLIFY(&size,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"]
12 -> 11 ;
11 [label="11: Exit A_while_loop: \n " color=yellow style=filled]
10 [label="10: Start A_while_loop:\nFormals: self:class A * items:class NSArray *\nLocals: size:int item:class NSArray * \n DECLARE_LOCALS(&return,&size,&item); [line 16]\n NULLIFY(&item,false); [line 16]\n NULLIFY(&self,false); [line 16]\n NULLIFY(&size,false); [line 16]\n " color=yellow style=filled]
10 -> 19 ;
9 [label="9: DeclStmt \n *&size:int =0 [line 9]\n APPLY_ABSTRACTION; [line 9]\n " shape="box"]
9 -> 4 ;
8 [label="8: ComppoundAssignStmt \n n$5=*&item:class NSArray * [line 11]\n n$4=_fun_NSArray_count(n$5:class NSArray *) virtual [line 11]\n n$6=*&size:int [line 11]\n *&size:int =(n$6 + n$4) [line 11]\n REMOVE_TEMPS(n$4,n$5,n$6); [line 11]\n NULLIFY(&item,false); [line 11]\n APPLY_ABSTRACTION; [line 11]\n " shape="box"]
8 -> 4 ;
7 [label="7: Prune (false branch) \n PRUNE((n$3 == 0), false); [line 10]\n REMOVE_TEMPS(n$1,n$2,n$3); [line 10]\n " shape="invhouse"]
7 -> 3 ;
6 [label="6: Prune (true branch) \n PRUNE((n$3 != 0), true); [line 10]\n REMOVE_TEMPS(n$1,n$2,n$3); [line 10]\n " shape="invhouse"]
6 -> 8 ;
5 [label="5: BinaryOperatorStmt: Assign \n n$2=*&items:class NSArray * [line 10]\n n$1=_fun_NSArray_nextObject(n$2:class NSArray *) virtual [line 10]\n *&item:class NSArray *=n$1 [line 10]\n n$3=*&item:class NSArray * [line 10]\n " shape="box"]
5 -> 6 ;
5 -> 7 ;
4 [label="4: + \n " ]
4 -> 5 ;
3 [label="3: Return Stmt \n NULLIFY(&item,false); [line 13]\n NULLIFY(&items,false); [line 13]\n n$0=*&size:int [line 13]\n *&return:int =n$0 [line 13]\n REMOVE_TEMPS(n$0); [line 13]\n NULLIFY(&size,false); [line 13]\n APPLY_ABSTRACTION; [line 13]\n " shape="box"]
3 -> 2 ;
2 [label="2: Exit A_fast_loop: \n " color=yellow style=filled]
1 [label="1: Start A_fast_loop:\nFormals: self:class A * items:class NSArray *\nLocals: size:int item:class NSArray * \n DECLARE_LOCALS(&return,&size,&item); [line 8]\n NULLIFY(&item,false); [line 8]\n NULLIFY(&self,false); [line 8]\n NULLIFY(&size,false); [line 8]\n " color=yellow style=filled]
1 -> 9 ;
}

@ -0,0 +1,25 @@
#import <Foundation/NSArray.h>
@interface A : NSObject
@end
@implementation A
- (int) fast_loop: (NSArray *) items {
int size = 0;
for (NSArray* item in items) {
size += [item count];
}
return size;
}
- (int) while_loop: (NSArray*) items {
int size = 0;
NSArray* item = nil;
while (item = [items nextObject]) {
size += [item count];
}
return size;
}
@end

@ -0,0 +1,47 @@
/*
* Copyright (c) 2013- Facebook.
* All rights reserved.
*/
package frontend.objc;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.DotFilesEqual.dotFileEqualTo;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import utils.DebuggableTemporaryFolder;
import utils.InferException;
import utils.InferRunner;
public class FastEnumerationTest {
@Rule
public DebuggableTemporaryFolder folder = new DebuggableTemporaryFolder();
@Test
public void whenCaptureRunOnTestThenDotFilesAreTheSame()
throws InterruptedException, IOException, InferException {
String exception_src =
"infer/tests/codetoanalyze/objc/frontend/fast_enumeration/Fast_enumeration.m";
String exception_dotty =
"infer/tests/codetoanalyze/objc/frontend/fast_enumeration/Fast_enumeration.dot";
ImmutableList<String> inferCmd =
InferRunner.createObjCInferCommandFrontend(folder, exception_src);
File newDotFile = InferRunner.runInferFrontend(inferCmd);
assertThat(
"In the capture of " + exception_src +
" the dotty files should be the same.",
newDotFile, dotFileEqualTo(exception_dotty));
}
}
Loading…
Cancel
Save