diff --git a/infer/src/al/CTL.ml b/infer/src/al/CTL.ml index cd6a5cd32..55323399e 100644 --- a/infer/src/al/CTL.ml +++ b/infer/src/al/CTL.ml @@ -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 -> diff --git a/infer/src/al/ComponentKit.ml b/infer/src/al/ComponentKit.ml index 8523ed5ae..6b811e421 100644 --- a/infer/src/al/ComponentKit.ml +++ b/infer/src/al/ComponentKit.ml @@ -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 diff --git a/infer/src/al/cPredicates.ml b/infer/src/al/cPredicates.ml index 02a772cfa..b31949d2c 100644 --- a/infer/src/al/cPredicates.ml +++ b/infer/src/al/cPredicates.ml @@ -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) -> diff --git a/infer/src/clang/cAst_utils.ml b/infer/src/clang/cAst_utils.ml index 2a2dfda0f..1eb1164bf 100644 --- a/infer/src/clang/cAst_utils.ml +++ b/infer/src/clang/cAst_utils.ml @@ -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 diff --git a/infer/src/clang/cAst_utils.mli b/infer/src/clang/cAst_utils.mli index 2d05eb7d9..7f144c1b7 100644 --- a/infer/src/clang/cAst_utils.mli +++ b/infer/src/clang/cAst_utils.mli @@ -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 diff --git a/infer/src/clang/cField_decl.ml b/infer/src/clang/cField_decl.ml index b6cd4f2eb..d20adc8ad 100644 --- a/infer/src/clang/cField_decl.ml +++ b/infer/src/clang/cField_decl.ml @@ -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 -> diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 123fb1fc1..4d5b4847a 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -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) *) diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 846cdabfe..533a5bf26 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -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 diff --git a/infer/src/clang/cMethod_trans.mli b/infer/src/clang/cMethod_trans.mli index 9b836d37e..8e2d09203 100644 --- a/infer/src/clang/cMethod_trans.mli +++ b/infer/src/clang/cMethod_trans.mli @@ -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 diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index febdac2b3..a10033e74 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -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 = diff --git a/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3.cpp b/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3.cpp new file mode 100644 index 000000000..8d529a27d --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3.cpp @@ -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; } diff --git a/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3.cpp.dot b/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3.cpp.dot new file mode 100644 index 000000000..21205c8a3 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3.cpp.dot @@ -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$G:int const ); [line 8, column 1]\n *&#GB$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$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" ; +} diff --git a/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3_header.h b/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3_header.h new file mode 100644 index 000000000..38b529524 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/frontend/globals/global_const3_header.h @@ -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;