[infer] Capture global initializer ondemand

Summary: This diff captures global initializers ondemand, like we do for functions defined in headers.

Reviewed By: ezgicicek

Differential Revision: D19346947

fbshipit-source-id: 05174e6a4
master
Sungkeun Cho 5 years ago committed by Facebook Github Bot
parent a79a819679
commit 16f18792f1

@ -168,14 +168,14 @@ let transition_decl_to_decl_via_accessor_for_property d desired_kind =
match decl_opt with
| Some (ObjCCategoryImplDecl (_, _, _, _, ocidi)) ->
let category_decls =
match CAst_utils.get_decl_opt_with_decl_ref ocidi.ocidi_category_decl with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocidi.ocidi_category_decl with
| Some (ObjCCategoryDecl (_, _, decls, _, _)) ->
List.filter ~f:decl_matches decls
| _ ->
[]
in
let class_decls =
match CAst_utils.get_decl_opt_with_decl_ref ocidi.ocidi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocidi.ocidi_class_interface with
| Some (ObjCInterfaceDecl (_, _, decls, _, _)) ->
List.filter ~f:decl_matches decls
| _ ->
@ -183,7 +183,7 @@ let transition_decl_to_decl_via_accessor_for_property d desired_kind =
in
category_decls @ class_decls
| Some (ObjCImplementationDecl (_, _, _, _, oidi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref oidi.oidi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt oidi.oidi_class_interface with
| Some (ObjCInterfaceDecl (_, _, decls, _, _)) ->
List.filter ~f:decl_matches decls
| _ ->
@ -207,7 +207,7 @@ let transition_decl_to_decl_via_accessor_for_property d desired_kind =
in
if not (ALVar.compare_str_with_alexp actual_kind desired_kind) then []
else
match CAst_utils.get_decl_opt_with_decl_ref mdi.omdi_property_decl with
match CAst_utils.get_decl_opt_with_decl_ref_opt mdi.omdi_property_decl with
| Some property_decl ->
(* clang handles most cases: property declarations with
accessor method declarations in the inferface; property
@ -245,7 +245,7 @@ let transition_decl_to_decl_via_super d =
| Clang_ast_t.ObjCImplementationDecl _ ->
do_ObjCImplementationDecl d
| Clang_ast_t.ObjCInterfaceDecl (_, _, _, _, idi) ->
decl_opt_to_ast_node_opt (CAst_utils.get_decl_opt_with_decl_ref idi.otdi_super)
decl_opt_to_ast_node_opt (CAst_utils.get_decl_opt_with_decl_ref_opt idi.otdi_super)
| _ ->
[]
@ -286,7 +286,9 @@ let transition_stmt_to_decl_via_pointer stmt =
| None ->
[] )
| DeclRefExpr (_, _, _, decl_ref_expr_info) -> (
match CAst_utils.get_decl_opt_with_decl_ref decl_ref_expr_info.Clang_ast_t.drti_decl_ref with
match
CAst_utils.get_decl_opt_with_decl_ref_opt decl_ref_expr_info.Clang_ast_t.drti_decl_ref
with
| Some decl ->
[Decl decl]
| None ->

@ -252,7 +252,9 @@ let component_with_unconventional_superclass_advice context an =
in
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) ->
let if_decl_opt = CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
let if_decl_opt =
CAst_utils.get_decl_opt_with_decl_ref_opt impl_decl_info.oidi_class_interface
in
if Option.is_some if_decl_opt && is_ck_context context an then
check_interface (Option.value_exn if_decl_opt)
else None
@ -306,7 +308,9 @@ let component_with_multiple_factory_methods_advice context an =
in
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) -> (
let if_decl_opt = CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
let if_decl_opt =
CAst_utils.get_decl_opt_with_decl_ref_opt impl_decl_info.oidi_class_interface
in
match if_decl_opt with Some d when is_ck_context context an -> check_interface d | _ -> [] )
| _ ->
[]
@ -322,7 +326,7 @@ let is_in_factory_method (context : CLintersContext.context) =
let interface_decl_opt =
match context.current_objc_class with
| Some (ObjCImplementationDecl (_, _, _, _, impl_decl_info)) ->
CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface
CAst_utils.get_decl_opt_with_decl_ref_opt impl_decl_info.oidi_class_interface
| _ ->
None
in

@ -109,7 +109,7 @@ let captured_variables_cxx_ref an =
let open Clang_ast_t in
let capture_var_is_cxx_ref reference_captured_vars captured_var =
let decl_ref_opt = captured_var.Clang_ast_t.bcv_variable in
match CAst_utils.get_decl_opt_with_decl_ref decl_ref_opt with
match CAst_utils.get_decl_opt_with_decl_ref_opt decl_ref_opt with
| Some (VarDecl (_, named_decl_info, qual_type, _))
| Some (ParmVarDecl (_, named_decl_info, qual_type, _))
| Some (ImplicitParamDecl (_, named_decl_info, qual_type, _)) -> (
@ -163,7 +163,7 @@ let rec is_subclass_of decl name =
let ndi = match super_ref.Clang_ast_t.dr_name with Some ni -> ni | _ -> assert false in
if ALVar.compare_str_with_alexp ndi.ni_name name then true
else
match CAst_utils.get_decl_opt_with_decl_ref (Some super_ref) with
match CAst_utils.get_decl_opt_with_decl_ref_opt (Some super_ref) with
| Some decl ->
is_subclass_of decl name
| None ->
@ -196,7 +196,7 @@ let is_objc_class_named an re = is_objc_interface_named an re || is_objc_impleme
let is_objc_category_interface_on_class_named an expected_name =
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCCategoryDecl (_, _, _, _, ocdi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref ocdi.odi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocdi.odi_class_interface with
| Some decl_ref ->
is_objc_interface_named (Decl decl_ref) expected_name
| _ ->
@ -209,7 +209,7 @@ let is_objc_category_interface_on_class_named an expected_name =
let is_objc_category_implementation_on_class_named an expected_name =
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCCategoryImplDecl (_, _, _, _, ocidi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref ocidi.ocidi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocidi.ocidi_class_interface with
| Some decl_ref ->
is_objc_interface_named (Decl decl_ref) expected_name
| _ ->
@ -227,7 +227,7 @@ let is_objc_category_on_class_named an re =
let is_objc_category_interface_on_subclass_of an expected_name =
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCCategoryDecl (_, _, _, _, ocdi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref ocdi.odi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocdi.odi_class_interface with
| Some decl_ref ->
is_subclass_of decl_ref expected_name
| _ ->
@ -240,7 +240,7 @@ let is_objc_category_interface_on_subclass_of an expected_name =
let is_objc_category_implementation_on_subclass_of an expected_name =
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCCategoryImplDecl (_, _, _, _, ocidi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref ocidi.ocidi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocidi.ocidi_class_interface with
| Some decl_ref ->
is_subclass_of decl_ref expected_name
| _ ->
@ -349,7 +349,7 @@ let is_objc_method_exposed context an =
let is_instance_method = mdi.omdi_is_instance_method in
match current_objc_container context with
| Some (ObjCImplementationDecl (_, _, _, _, oidi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref oidi.oidi_class_interface with
match CAst_utils.get_decl_opt_with_decl_ref_opt oidi.oidi_class_interface with
| Some (ObjCInterfaceDecl (_, _, decl_list, _, otdi)) ->
decl_list_has_objc_method decl_list method_name is_instance_method
|| List.exists
@ -364,7 +364,7 @@ let is_objc_method_exposed context an =
| _ ->
false )
| Some (ObjCCategoryImplDecl (_, _, _, _, ocidi)) -> (
match CAst_utils.get_decl_opt_with_decl_ref ocidi.ocidi_category_decl with
match CAst_utils.get_decl_opt_with_decl_ref_opt ocidi.ocidi_category_decl with
| Some (ObjCCategoryDecl (_, _, decl_list, _, _)) ->
decl_list_has_objc_method decl_list method_name is_instance_method
| _ ->
@ -419,7 +419,7 @@ let objc_message_receiver context an =
match current_objc_container context with
| Some container ->
let decl_ref_opt = CAst_utils.get_superclass_curr_class_objc_from_decl container in
CAst_utils.get_decl_opt_with_decl_ref decl_ref_opt
CAst_utils.get_decl_opt_with_decl_ref_opt decl_ref_opt
| _ ->
None )
| `Class qt ->
@ -739,7 +739,7 @@ let is_method_property_accessor_of_ivar an context =
| Some (ObjCMethodDecl (_, _, mdi)) ->
if mdi.omdi_is_property_accessor then
let property_opt = mdi.omdi_property_decl in
match CAst_utils.get_decl_opt_with_decl_ref property_opt with
match CAst_utils.get_decl_opt_with_decl_ref_opt property_opt with
| Some (ObjCPropertyDecl (_, _, pdi)) -> (
match pdi.opdi_ivar_decl with
| Some decl_ref ->
@ -1400,7 +1400,7 @@ let rec get_decl_attributes an =
| Stmt (ImplicitCastExpr (_, [stmt], _, _)) ->
get_decl_attributes (Stmt stmt)
| Stmt (DeclRefExpr (_, _, _, drti)) -> (
match CAst_utils.get_decl_opt_with_decl_ref drti.drti_decl_ref with
match CAst_utils.get_decl_opt_with_decl_ref_opt drti.drti_decl_ref with
| Some decl ->
get_decl_attributes (Decl decl)
| None ->
@ -1423,7 +1423,7 @@ let rec get_decl_attributes_for_callexpr_param an =
get_decl_attributes_for_callexpr_param (Stmt stmt)
| Stmt (DeclRefExpr (si, _, _, drti)) -> (
L.debug Linters Verbose "#####POINTER LOOP UP: '%i'@\n" si.si_pointer ;
match CAst_utils.get_decl_opt_with_decl_ref drti.drti_decl_ref with
match CAst_utils.get_decl_opt_with_decl_ref_opt drti.drti_decl_ref with
| Some (FunctionDecl (_, _, _, fdi)) ->
List.fold fdi.fdi_parameters ~f:(fun acc p -> List.append (get_attr_param p) acc) ~init:[]
| Some (ParmVarDecl _ as d) ->

@ -127,13 +127,13 @@ let get_stmt_opt stmt_ptr_opt source_range =
match stmt_ptr_opt with Some stmt_ptr -> get_stmt stmt_ptr source_range | None -> None
let get_decl_opt_with_decl_ref decl_ref_opt =
match decl_ref_opt with
| Some decl_ref ->
L.debug Capture Verbose "#####POINTER LOOK UP: '%i'@\n" decl_ref.Clang_ast_t.dr_decl_pointer ;
get_decl decl_ref.Clang_ast_t.dr_decl_pointer
| None ->
None
let get_decl_opt_with_decl_ref decl_ref =
L.debug Capture Verbose "#####POINTER LOOK UP: '%i'@\n" decl_ref.Clang_ast_t.dr_decl_pointer ;
get_decl decl_ref.Clang_ast_t.dr_decl_pointer
let get_decl_opt_with_decl_ref_opt decl_ref_opt =
Option.bind decl_ref_opt ~f:get_decl_opt_with_decl_ref
let get_property_of_ivar decl_ptr = Int.Table.find ClangPointers.ivar_to_property_table decl_ptr
@ -350,24 +350,24 @@ let rec get_super_if decl =
| Some (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) ->
(* Try getting the super ref through the impl info, and fall back to
getting the if decl first and getting the super ref through it. *)
let super_ref = get_decl_opt_with_decl_ref impl_decl_info.oidi_super in
let super_ref = get_decl_opt_with_decl_ref_opt impl_decl_info.oidi_super in
if Option.is_some super_ref then super_ref
else get_super_if (get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface)
else get_super_if (get_decl_opt_with_decl_ref_opt impl_decl_info.oidi_class_interface)
| Some (Clang_ast_t.ObjCInterfaceDecl (_, _, _, _, interface_decl_info)) ->
get_decl_opt_with_decl_ref interface_decl_info.otdi_super
get_decl_opt_with_decl_ref_opt interface_decl_info.otdi_super
| _ ->
None
let get_super_ObjCImplementationDecl impl_decl_info =
let objc_interface_decl_current =
get_decl_opt_with_decl_ref impl_decl_info.Clang_ast_t.oidi_class_interface
get_decl_opt_with_decl_ref_opt impl_decl_info.Clang_ast_t.oidi_class_interface
in
let objc_interface_decl_super = get_super_if objc_interface_decl_current in
let objc_implementation_decl_super =
match objc_interface_decl_super with
| Some (ObjCInterfaceDecl (_, _, _, _, interface_decl_info)) ->
get_decl_opt_with_decl_ref interface_decl_info.otdi_implementation
get_decl_opt_with_decl_ref_opt interface_decl_info.otdi_implementation
| _ ->
None
in

@ -25,7 +25,9 @@ val get_stmt_exn : Clang_ast_t.pointer -> Clang_ast_t.source_range -> Clang_ast_
val get_stmt_opt : Clang_ast_t.pointer option -> Clang_ast_t.source_range -> Clang_ast_t.stmt option
val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option
val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref -> Clang_ast_t.decl option
val get_decl_opt_with_decl_ref_opt : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option
val get_property_of_ivar : Clang_ast_t.pointer -> Clang_ast_t.decl option

@ -78,7 +78,7 @@ let get_fields qual_type_to_sil_type tenv class_tname decl_list =
| ObjCPropertyDecl (_, _, obj_c_property_decl_info) -> (
let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
let property_attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in
match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
match CAst_utils.get_decl_opt_with_decl_ref_opt ivar_decl_ref with
| Some (ObjCIvarDecl (_, name_info, qual_type, _, _)) ->
let field = get_sil_field name_info qual_type property_attributes in
CGeneral_utils.add_no_duplicates_fields field fields
@ -86,7 +86,7 @@ let get_fields qual_type_to_sil_type tenv class_tname decl_list =
fields )
| ObjCPropertyImplDecl (_, obj_c_property_impl_decl_info) -> (
let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in
match CAst_utils.get_decl_opt_with_decl_ref property_decl_opt with
match CAst_utils.get_decl_opt_with_decl_ref_opt property_decl_opt with
| Some decl ->
get_field fields decl
| None ->

@ -151,10 +151,10 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron
let process_property_implementation trans_unit_ctx tenv cfg curr_class
obj_c_property_impl_decl_info =
let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in
match CAst_utils.get_decl_opt_with_decl_ref property_decl_opt with
match CAst_utils.get_decl_opt_with_decl_ref_opt property_decl_opt with
| Some (ObjCPropertyDecl (_, _, obj_c_property_decl_info)) ->
let process_accessor pointer =
match CAst_utils.get_decl_opt_with_decl_ref pointer with
match CAst_utils.get_decl_opt_with_decl_ref_opt pointer with
| Some (ObjCMethodDecl _ as dec) ->
process_method_decl ~set_objc_accessor_attr:true trans_unit_ctx tenv cfg curr_class
dec
@ -389,16 +389,22 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron
(* safe to Option.get because it's a global *)
Option.value_exn (Pvar.get_initializer_pname global)
in
let ms =
CMethodSignature.mk procname None [] (Typ.void, Annot.Item.empty) []
decl_info.Clang_ast_t.di_source_range ClangMethodKind.C_FUNCTION None None None `None
in
let stmt_info =
{si_pointer= CAst_utils.get_fresh_pointer (); si_source_range= decl_info.di_source_range}
in
let body = Clang_ast_t.DeclStmt (stmt_info, [], [dec]) in
ignore (CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] []) ;
add_method trans_unit_ctx tenv cfg CContext.ContextNoCls procname body ms None None []
if
CMethod_trans.should_create_procdesc cfg procname ~defined:true
~set_objc_accessor_attr:false
then (
let ms =
CMethodSignature.mk procname None [] (Typ.void, Annot.Item.empty) []
decl_info.Clang_ast_t.di_source_range ClangMethodKind.C_FUNCTION None None None
`None
in
let stmt_info =
{ si_pointer= CAst_utils.get_fresh_pointer ()
; si_source_range= decl_info.di_source_range }
in
let body = Clang_ast_t.DeclStmt (stmt_info, [], [dec]) in
ignore (CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] []) ;
add_method trans_unit_ctx tenv cfg CContext.ContextNoCls procname body ms None None [] )
(* Note that C and C++ records are treated the same way
Skip translating implicit struct declarations, unless they have
full definition (which happens with C++ lambdas) *)

@ -122,7 +122,7 @@ let get_objc_method_data obj_c_message_expr_info =
(selector, pointer, MCStatic)
let should_create_procdesc cfg procname defined set_objc_accessor_attr =
let should_create_procdesc cfg procname ~defined ~set_objc_accessor_attr =
match Procname.Hash.find cfg procname with
| previous_procdesc ->
let is_defined_previous = Procdesc.is_defined previous_procdesc in
@ -152,7 +152,7 @@ let get_objc_property_accessor tenv ms =
match CAst_utils.get_decl_opt ms.CMethodSignature.pointer_to_property_opt with
| Some (ObjCPropertyDecl (_, _, obj_c_property_decl_info)) -> (
let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
match CAst_utils.get_decl_opt_with_decl_ref_opt ivar_decl_ref with
| Some (ObjCIvarDecl (_, name_decl_info, _, _, _)) -> (
let class_tname =
Typ.Name.Objc.from_qual_name
@ -265,7 +265,7 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg t
Procdesc.set_start_node procdesc start_node ;
Procdesc.set_exit_node procdesc exit_node )
in
if should_create_procdesc cfg proc_name defined set_objc_accessor_attr then (
if should_create_procdesc cfg proc_name ~defined ~set_objc_accessor_attr then (
create_new_procdesc () ; true )
else false

@ -18,6 +18,12 @@ type method_call_type = MCVirtual | MCNoVirtual | MCStatic [@@deriving compare]
val equal_method_call_type : method_call_type -> method_call_type -> bool
val should_create_procdesc :
Cfg.t -> Procname.t -> defined:bool -> set_objc_accessor_attr:bool -> bool
(** Return if a procdesc should be added or not. It returns [false] when the same name of procdesc
was added previously. [defined] represents if the function body is non-empty.
[set_objc_accessor_attr] represents if the function is a getter/setter in Obj-C. *)
val create_local_procdesc :
?set_objc_accessor_attr:bool
-> CFrontend_config.translation_unit_context

@ -188,15 +188,29 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
else f {trans_state with priority= Free} e
let call_translation context decl =
let open CContext in
(* translation will reset Ident counter, save it's state and restore it afterwards *)
(* Translation will reset Ident counter, save it's state and restore it afterwards *)
let keep_ident_counter ~f =
let ident_state = Ident.NameGenerator.get_current () in
F.translate_one_declaration context.translation_unit_context context.tenv context.cfg
`Translation decl ;
f () ;
Ident.NameGenerator.set_current ident_state
let call_translation context decl =
let open CContext in
keep_ident_counter ~f:(fun () ->
F.translate_one_declaration context.translation_unit_context context.tenv context.cfg
`Translation decl )
let global_var_decl_translation context decl_ref =
let open CContext in
keep_ident_counter ~f:(fun () ->
CAst_utils.get_decl_opt_with_decl_ref decl_ref
|> Option.iter ~f:(fun decl ->
F.translate_one_declaration context.translation_unit_context context.tenv context.cfg
`Translation decl ) )
let create_var_exp_tmp_var trans_state expr_info ~clang_pointer ~var_name =
let context = trans_state.context in
let procdesc = context.CContext.procdesc in
@ -782,12 +796,26 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
in
L.(debug Capture Verbose) "@\n@\n PVAR ='%s'@\n@\n" (Pvar.to_string pvar) ;
let res_trans = mk_trans_result return empty_control in
match typ.desc with
| Tptr (_, Pk_reference) ->
(* dereference pvar due to the behavior of reference types in clang's AST *)
dereference_value_from_result stmt_info.Clang_ast_t.si_source_range sil_loc res_trans
| _ ->
res_trans
let res_trans =
match typ.desc with
| Tptr (_, Pk_reference) ->
(* dereference pvar due to the behavior of reference types in clang's AST *)
dereference_value_from_result stmt_info.Clang_ast_t.si_source_range sil_loc res_trans
| _ ->
res_trans
in
(* TODO: For now, it does not generate the initializers for static local variables. This is
unsound because a static local varaible should be initialized once globally. On the other
hand, currently static local variables are initialized in the function body, i.e.,
initializing every time the function is called.
While we should move the initialization out the function body to solve the issue, it is not
good at the moment due to the name conflict of the initializers. Infer introduces the
initializer names like [__infer_globals_initializer_\[var\]]. Thus, if multiple functions
have static local variables with the same name, their initializer names will conflict. *)
if Pvar.is_global pvar && not (Pvar.is_static_local pvar) then
global_var_decl_translation context decl_ref ;
res_trans
and decl_ref_trans ?(is_constructor_init = false) ~context trans_state stmt_info decl_ref =

@ -0,0 +1,10 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "global_const3_header.h"
void test() { int i = G; }

@ -0,0 +1,25 @@
/* @generated */
digraph cfg {
"__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_1" [label="1: Start __infer_globals_initializer_G\nFormals: \nLocals: \n " color=yellow style=filled]
"__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_1" -> "__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_3" ;
"__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_2" [label="2: Exit __infer_globals_initializer_G \n " color=yellow style=filled]
"__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_3" [label="3: DeclStmt \n VARIABLE_DECLARED(#GB<codetoanalyze/cpp/frontend/globals/global_const3.cpp|ice>$G:int const ); [line 8, column 1]\n *&#GB<codetoanalyze/cpp/frontend/globals/global_const3.cpp|ice>$G:int=0 [line 8, column 1]\n " shape="box"]
"__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_3" -> "__infer_globals_initializer_G.b72b93e9e8b8fb24886062df626ec074_2" ;
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_1" [label="1: Start test\nFormals: \nLocals: i:int \n " color=yellow style=filled]
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_1" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_3" ;
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_2" [label="2: Exit test \n " color=yellow style=filled]
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_3" [label="3: DeclStmt \n VARIABLE_DECLARED(i:int); [line 10, column 15]\n n$0=*&#GB<codetoanalyze/cpp/frontend/globals/global_const3.cpp|ice>$G:int [line 10, column 23]\n *&i:int=n$0 [line 10, column 15]\n " shape="box"]
"test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_3" -> "test#18241244337164948030.afc14f193ad97442f67ac7183be789bc_2" ;
}

@ -0,0 +1,8 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const int G = 0;
Loading…
Cancel
Save