[siof] take POD into account

Summary:
SIOF is only for interactions between objects of non-POD types. Previously the
checker was also reporting for POD types.

Reviewed By: akotulski

Differential Revision: D4197620

fbshipit-source-id: 7c56571
master
Jules Villard 9 years ago committed by Facebook Github Bot
parent 05c72f510a
commit 17179d4275

@ -1 +1 @@
Subproject commit 248d630ea8a64a01ca56ccb87f97acd707610660 Subproject commit 18904710494629ff27a5350d715f3a2a228970b6

@ -26,7 +26,7 @@ type pvar_kind =
| Abduced_retvar Procname.t Location.t /** synthetic variable to represent return value */ | Abduced_retvar Procname.t Location.t /** synthetic variable to represent return value */
| Abduced_ref_param Procname.t t Location.t | Abduced_ref_param Procname.t t Location.t
/** synthetic variable to represent param passed by reference */ /** synthetic variable to represent param passed by reference */
| Global_var (DB.source_file, bool) /** global variable: translation unit + is it compile constant? */ | Global_var (DB.source_file, bool, bool) /** global variable: translation unit + is it compile constant? + is it POD? */
| Seed_var /** variable used to store the initial value of formal parameters */ | Seed_var /** variable used to store the initial value of formal parameters */
/** Names for program variables. */ /** Names for program variables. */
and t = {pv_name: Mangled.t, pv_kind: pvar_kind}; and t = {pv_name: Mangled.t, pv_kind: pvar_kind};
@ -62,12 +62,17 @@ let rec pvar_kind_compare k1 k2 =>
} }
| (Abduced_ref_param _, _) => (-1) | (Abduced_ref_param _, _) => (-1)
| (_, Abduced_ref_param _) => 1 | (_, Abduced_ref_param _) => 1
| (Global_var (f1, b1), Global_var (f2, b2)) => | (Global_var (f1, const1, pod1), Global_var (f2, const2, pod2)) =>
let n = DB.source_file_compare f1 f2; let n = DB.source_file_compare f1 f2;
if (n != 0) { if (n != 0) {
n n
} else { } else {
bool_compare b1 b2 let n = bool_compare const1 const2;
if (n != 0) {
n
} else {
bool_compare pod1 pod2
}
} }
| (Global_var _, _) => (-1) | (Global_var _, _) => (-1)
| (_, Global_var _) => 1 | (_, Global_var _) => 1
@ -111,9 +116,21 @@ let rec _pp f pv => {
} else { } else {
F.fprintf f "%a$%a%a|abducedRefParam" Procname.pp n Location.pp l Mangled.pp name F.fprintf f "%a$%a%a|abducedRefParam" Procname.pp n Location.pp l Mangled.pp name
} }
| Global_var (fname, b) => | Global_var (fname, is_const, is_pod) =>
F.fprintf F.fprintf
f "#GB<%s%s>$%a" (DB.source_file_to_string fname) (if b {"|const"} else {""}) Mangled.pp name f
"#GB<%s%s%s>$%a"
(DB.source_file_to_string fname)
(if is_const {"|const"} else {""})
(
if (not is_pod) {
"|!pod"
} else {
""
}
)
Mangled.pp
name
| Seed_var => F.fprintf f "old_%a" Mangled.pp name | Seed_var => F.fprintf f "old_%a" Mangled.pp name
} }
}; };
@ -327,9 +344,9 @@ let mk_callee (name: Mangled.t) (proc_name: Procname.t) :t => {
/** create a global variable with the given name */ /** create a global variable with the given name */
let mk_global is_constexpr::is_constexpr=false (name: Mangled.t) fname :t => { let mk_global is_constexpr::is_constexpr=false is_pod::is_pod=true (name: Mangled.t) fname :t => {
pv_name: name, pv_name: name,
pv_kind: Global_var (fname, is_constexpr) pv_kind: Global_var (fname, is_constexpr, is_pod)
}; };
@ -354,16 +371,22 @@ let mk_abduced_ref_param (proc_name: Procname.t) (pv: t) (loc: Location.t) :t =>
let get_source_file pvar => let get_source_file pvar =>
switch pvar.pv_kind { switch pvar.pv_kind {
| Global_var (f, _) => Some f | Global_var (f, _, _) => Some f
| _ => None | _ => None
}; };
let is_compile_constant pvar => let is_compile_constant pvar =>
switch pvar.pv_kind { switch pvar.pv_kind {
| Global_var (_, b) => b | Global_var (_, b, _) => b
| _ => false | _ => false
}; };
let is_pod pvar =>
switch pvar.pv_kind {
| Global_var (_, _, b) => b
| _ => true
};
let get_initializer_pname {pv_name, pv_kind} => let get_initializer_pname {pv_name, pv_kind} =>
switch pv_kind { switch pv_kind {
| Global_var _ => | Global_var _ =>

@ -104,7 +104,7 @@ let mk_callee: Mangled.t => Procname.t => t;
/** create a global variable with the given name */ /** create a global variable with the given name */
let mk_global: is_constexpr::bool? => Mangled.t => DB.source_file => t; let mk_global: is_constexpr::bool? => is_pod::bool? => Mangled.t => DB.source_file => t;
/** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! */ /** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! */
@ -139,10 +139,16 @@ let to_string: t => string;
let get_source_file: t => option DB.source_file; let get_source_file: t => option DB.source_file;
/** Is the variable's value a compile-time constant? Always [false] for non-globals. */ /** Is the variable's value a compile-time constant? Always (potentially incorrectly) returns
[false] for non-globals. */
let is_compile_constant: t => bool; let is_compile_constant: t => bool;
/** Is the variable's type a "Plain Old Data" type (C++)? Always (potentially incorrectly) returns
[true] for non-globals. */
let is_pod: t => bool;
/** Get the procname of the initializer function for the given global variable */ /** Get the procname of the initializer function for the given global variable */
let get_initializer_pname: t => option Procname.t; let get_initializer_pname: t => option Procname.t;

@ -27,20 +27,11 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
module Domain = SiofDomain module Domain = SiofDomain
type extras = ProcData.no_extras type extras = ProcData.no_extras
let is_semantically_compile_constant tenv pdesc pv = let get_globals astate loc e =
match Pvar.get_initializer_pname pv with
| Some pname -> (
match Summary.read_summary tenv pdesc pname with
| Some (Domain.NonBottom _) -> false
| Some Domain.Bottom | None -> true
)
| None -> true
let get_globals tenv astate pdesc loc e =
let is_dangerous_global pv = let is_dangerous_global pv =
Pvar.is_global pv Pvar.is_global pv
&& not (Pvar.is_compile_constant pv && not (Pvar.is_pod pv)
|| is_semantically_compile_constant tenv pdesc pv) in && not (Pvar.is_compile_constant pv) in
let globals = Exp.get_vars e |> snd |> IList.filter is_dangerous_global in let globals = Exp.get_vars e |> snd |> IList.filter is_dangerous_global in
if globals = [] then if globals = [] then
Domain.Bottom Domain.Bottom
@ -55,9 +46,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
globals in globals in
Domain.NonBottom globals_trace Domain.NonBottom globals_trace
let add_params_globals astate tenv pdesc loc params = let add_params_globals astate loc params =
IList.map fst params IList.map fst params
|> IList.map (fun e -> get_globals tenv astate pdesc loc e) |> IList.map (fun e -> get_globals astate loc e)
|> IList.fold_left Domain.join astate |> IList.fold_left Domain.join astate
let at_least_bottom = let at_least_bottom =
@ -67,7 +58,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
| Load (_, exp, _, loc) | Load (_, exp, _, loc)
| Store (_, _, exp, loc) | Store (_, _, exp, loc)
| Prune (exp, loc, _, _) -> | Prune (exp, loc, _, _) ->
Domain.join astate (get_globals tenv astate pdesc loc exp) Domain.join astate (get_globals astate loc exp)
| Call (_, Const (Cfun callee_pname), params, loc, _) -> | Call (_, Const (Cfun callee_pname), params, loc, _) ->
let callsite = CallSite.make callee_pname loc in let callsite = CallSite.make callee_pname loc in
let callee_globals = let callee_globals =
@ -76,13 +67,13 @@ module TransferFunctions (CFG : ProcCfg.S) = struct
Domain.NonBottom (SiofTrace.with_callsite trace callsite) Domain.NonBottom (SiofTrace.with_callsite trace callsite)
| _ -> | _ ->
Domain.Bottom in Domain.Bottom in
add_params_globals astate tenv pdesc loc params add_params_globals astate loc params
|> Domain.join callee_globals |> Domain.join callee_globals
|> |>
(* make sure it's not Bottom: we made a function call so this needs initialization *) (* make sure it's not Bottom: we made a function call so this needs initialization *)
at_least_bottom at_least_bottom
| Call (_, _, params, loc, _) -> | Call (_, _, params, loc, _) ->
add_params_globals astate tenv pdesc loc params add_params_globals astate loc params
|> |>
(* make sure it's not Bottom: we made a function call so this needs initialization *) (* make sure it's not Bottom: we made a function call so this needs initialization *)
at_least_bottom at_least_bottom
@ -98,7 +89,19 @@ module Analyzer =
module Interprocedural = Analyzer.Interprocedural (Summary) module Interprocedural = Analyzer.Interprocedural (Summary)
let is_foreign tu_opt v =
let is_orig_file f = match tu_opt with
| Some orig_file ->
let orig_path = DB.source_file_to_abs_path orig_file in
string_equal orig_path (DB.source_file_to_abs_path f)
| None -> assert false in
Option.map_default (fun f -> not (is_orig_file f)) false (Pvar.get_source_file v)
let report_siof tenv trace pdesc gname loc = let report_siof tenv trace pdesc gname loc =
let tu_opt =
let attrs = Procdesc.get_attributes pdesc in
attrs.ProcAttributes.translation_unit in
let trace_of_pname pname = let trace_of_pname pname =
match Summary.read_summary tenv pdesc pname with match Summary.read_summary tenv pdesc pname with
| Some (SiofDomain.NonBottom summary) -> summary | Some (SiofDomain.NonBottom summary) -> summary
@ -129,6 +132,7 @@ let report_siof tenv trace pdesc gname loc =
let report_one_path ((_, path) as sink_path) = let report_one_path ((_, path) as sink_path) =
let final_sink = fst (IList.hd path) in let final_sink = fst (IList.hd path) in
if is_foreign tu_opt (SiofTrace.Sink.kind final_sink) then (
let description = let description =
F.asprintf F.asprintf
"The initializer of %s accesses global variables in another translation unit: %a" "The initializer of %s accesses global variables in another translation unit: %a"
@ -138,23 +142,17 @@ let report_siof tenv trace pdesc gname loc =
let caller_pname = Procdesc.get_proc_name pdesc in let caller_pname = Procdesc.get_proc_name pdesc in
let msg = Localise.to_string Localise.static_initialization_order_fiasco in let msg = Localise.to_string Localise.static_initialization_order_fiasco in
let exn = Exceptions.Checkers (msg, Localise.verbatim_desc description) in let exn = Exceptions.Checkers (msg, Localise.verbatim_desc description) in
Reporting.log_error caller_pname ~loc ~ltr exn in Reporting.log_error caller_pname ~loc ~ltr exn
); in
IList.iter report_one_path (SiofTrace.get_reportable_sink_paths trace ~trace_of_pname) IList.iter report_one_path (SiofTrace.get_reportable_sink_paths trace ~trace_of_pname)
let siof_check tenv pdesc gname = function let siof_check tenv pdesc gname = function
| Some (SiofDomain.NonBottom post) -> | Some (SiofDomain.NonBottom post) ->
let attrs = Procdesc.get_attributes pdesc in let attrs = Procdesc.get_attributes pdesc in
let is_orig_file f = match attrs.ProcAttributes.translation_unit with
| Some orig_file ->
let orig_path = DB.source_file_to_abs_path orig_file in
string_equal orig_path (DB.source_file_to_abs_path f)
| None -> false in
let is_foreign v = Option.map_default
(fun f -> not (is_orig_file f)) false (Pvar.get_source_file v) in
let foreign_global_sinks = let foreign_global_sinks =
SiofTrace.Sinks.filter SiofTrace.Sinks.filter
(fun sink -> is_foreign (SiofTrace.Sink.kind sink)) (fun sink -> is_foreign attrs.ProcAttributes.translation_unit (SiofTrace.Sink.kind sink))
(SiofTrace.sinks post) in (SiofTrace.sinks post) in
if not (SiofTrace.Sinks.is_empty foreign_global_sinks) if not (SiofTrace.Sinks.is_empty foreign_global_sinks)
then report_siof tenv post pdesc gname attrs.ProcAttributes.loc; then report_siof tenv post pdesc gname attrs.ProcAttributes.loc;

@ -221,14 +221,14 @@ struct
| Some dec -> | Some dec ->
Logging.out "Methods of %s skipped\n" (Ast_utils.string_of_decl dec) Logging.out "Methods of %s skipped\n" (Ast_utils.string_of_decl dec)
| None -> ()) | None -> ())
| VarDecl (decl_info, named_decl_info, _, ({ vdi_is_global; vdi_init_expr } as vdi)) | VarDecl (decl_info, named_decl_info, qt, ({ vdi_is_global; vdi_init_expr } as vdi))
when vdi_is_global && Option.is_some vdi_init_expr -> when vdi_is_global && Option.is_some vdi_init_expr ->
(* create a fake procedure that initializes the global variable so that the variable (* create a fake procedure that initializes the global variable so that the variable
initializer can be analyzed by the backend (eg, the SIOF checker) *) initializer can be analyzed by the backend (eg, the SIOF checker) *)
let procname = let procname =
(* create the corresponding global variable to get the right pname for its (* create the corresponding global variable to get the right pname for its
initializer *) initializer *)
let global = General_utils.mk_sil_global_var trans_unit_ctx named_decl_info vdi in let global = General_utils.mk_sil_global_var trans_unit_ctx named_decl_info vdi qt in
(* safe to Option.get because it's a global *) (* safe to Option.get because it's a global *)
Option.get (Pvar.get_initializer_pname global) in Option.get (Pvar.get_initializer_pname global) in
let ms = CMethod_signature.make_ms procname [] Ast_expressions.create_void_type let ms = CMethod_signature.make_ms procname [] Ast_expressions.create_void_type

@ -781,20 +781,33 @@ struct
name_string, mangled name_string, mangled
let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name=fun _ x -> x) let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name=fun _ x -> x)
named_decl_info var_decl_info = named_decl_info var_decl_info qt =
let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in
let translation_unit = let translation_unit =
match var_decl_info.Clang_ast_t.vdi_storage_class with match (var_decl_info.Clang_ast_t.vdi_storage_class,
| Some "extern" -> var_decl_info.Clang_ast_t.vdi_init_expr) with
| Some "extern", None ->
(* some compilers simply disregard "extern" when the global is given some initialisation
code, which is why we make sure that [vdi_init_expr] is None here... *)
DB.source_file_empty DB.source_file_empty
| _ -> | _ ->
source_file in source_file in
let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in
Pvar.mk_global ~is_constexpr (mk_name name_string simple_name) translation_unit let is_pod =
Ast_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr
|> Option.map_default (function
| Clang_ast_t.RecordType(_, decl_ptr) -> Ast_utils.get_decl decl_ptr
| _ -> None) None
|> Option.map_default (function
| Clang_ast_t.CXXRecordDecl(_, _, _, _, _, _, _, {xrdi_is_pod})
| Clang_ast_t.ClassTemplateSpecializationDecl(_, _, _, _, _, _, _, {xrdi_is_pod}, _) ->
xrdi_is_pod
| _ -> true) true in
Pvar.mk_global ~is_constexpr ~is_pod (mk_name name_string simple_name) translation_unit
let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname = let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname =
match decl_info_type_ptr_opt with match decl_info_type_ptr_opt with
| Some (decl_info, _, var_decl_info, should_be_mangled) -> | Some (decl_info, qt, var_decl_info, should_be_mangled) ->
let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in
if var_decl_info.Clang_ast_t.vdi_is_global then if var_decl_info.Clang_ast_t.vdi_is_global then
let mk_name = let mk_name =
@ -802,7 +815,7 @@ struct
Some (fun name_string _ -> Some (fun name_string _ ->
Mangled.from_string ((Procname.to_string outer_procname) ^ "_" ^ name_string)) Mangled.from_string ((Procname.to_string outer_procname) ^ "_" ^ name_string))
else None in else None in
mk_sil_global_var trans_unit_ctx ?mk_name named_decl_info var_decl_info mk_sil_global_var trans_unit_ctx ?mk_name named_decl_info var_decl_info qt
else if not should_be_mangled then Pvar.mk simple_name procname else if not should_be_mangled then Pvar.mk simple_name procname
else else
let start_location = fst decl_info.Clang_ast_t.di_source_range in let start_location = fst decl_info.Clang_ast_t.di_source_range in

@ -247,7 +247,7 @@ sig
val mk_sil_global_var : CFrontend_config.translation_unit_context -> val mk_sil_global_var : CFrontend_config.translation_unit_context ->
?mk_name:(string -> Mangled.t -> Mangled.t) -> ?mk_name:(string -> Mangled.t -> Mangled.t) ->
Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> Pvar.t Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> Clang_ast_t.qual_type -> Pvar.t
val mk_sil_var : CFrontend_config.translation_unit_context -> Clang_ast_t.named_decl_info -> val mk_sil_var : CFrontend_config.translation_unit_context -> Clang_ast_t.named_decl_info ->
var_info option -> Procname.t -> Procname.t -> Pvar.t var_info option -> Procname.t -> Procname.t -> Pvar.t

@ -19,7 +19,8 @@ SOURCES = \
siof/pod_across_translation_units-1.cpp \ siof/pod_across_translation_units-1.cpp \
siof/pod_across_translation_units-2.cpp \ siof/pod_across_translation_units-2.cpp \
siof/pod_same_translation_unit.cpp \ siof/pod_same_translation_unit.cpp \
siof/siof_across_translation_units-1.cpp \ siof/siof.cpp \
siof/siof_across_translation_units-2.cpp \ siof/siof_templated.cpp \
siof/siof_different_tu.cpp \
include $(TESTS_DIR)/clang.make include $(TESTS_DIR)/clang.make

@ -1,4 +1,10 @@
siof/const_use.cpp, __infer_globals_initializer_use_u, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of use_u,access to u] siof/siof.cpp, __infer_globals_initializer_X::static_pod_accesses_non_pod, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of X::static_pod_accesses_non_pod,call to access_to_non_pod,access to global_object2]
siof/pod_across_translation_units-1.cpp, __infer_globals_initializer_x, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of x,call to baz,call to bar,call to foo,access to y] siof/siof.cpp, __infer_globals_initializer_another_global_object, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object,call to SomeOtherNonPODObject_SomeOtherNonPODObject,access to extern_global_object]
siof/siof_across_translation_units-1.cpp, __infer_globals_initializer_another_global_object, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object,access to another_global_object] siof/siof.cpp, __infer_globals_initializer_another_global_object2, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object2,call to access_to_non_pod,access to global_object2]
siof/siof_across_translation_units-1.cpp, __infer_globals_initializer_another_global_object, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object,call to SomeOtherObject_SomeOtherObject,access to global_object] siof/siof.cpp, __infer_globals_initializer_another_global_object3, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object3,call to access_to_templated_non_pod,access to global_object3]
siof/siof.cpp, __infer_globals_initializer_initWithGlobal, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of initWithGlobal,call to getGlobalNonPOD,access to global_object2]
siof/siof.cpp, __infer_globals_initializer_initWithStatic, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of initWithStatic,call to getFunctionStaticNonPOD,access to getFunctionStaticNonPOD_instance]
siof/siof.cpp, __infer_globals_initializer_pod_accesses_non_pod, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of pod_accesses_non_pod,call to access_to_non_pod,access to global_object2]
siof/siof_templated.cpp, __infer_globals_initializer_another_templated_global_object, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_templated_global_object,call to SomeOtherTemplatedNonPODObject<_Bool>_SomeOtherTemplatedNonPODObject,access to extern_global_object]
siof/siof_templated.cpp, __infer_globals_initializer_another_templated_global_object2, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_templated_global_object2,call to access_to_non_pod,access to global_object2]
siof/siof_templated.cpp, __infer_globals_initializer_another_templated_global_object3, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_templated_global_object3,call to access_to_templated_non_pod,access to global_object3]

@ -0,0 +1,43 @@
/*
* 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.
*/
#include "siof_types.h"
extern SomeNonPODObject extern_global_object;
SomeNonPODObject global_object;
extern int access_to_non_pod();
struct SomeOtherNonPODObject {
SomeOtherNonPODObject() {
global_object.some_method(); // OK, same translation unit
extern_global_object.some_method(); // bad, different translation unit
};
SomeOtherNonPODObject(int i) {
global_object.some_method(); // OK, same translation unit
};
};
SomeOtherNonPODObject another_global_object; // SIOF!
SomeOtherNonPODObject another_global_object2(access_to_non_pod()); // SIOF!
SomeOtherNonPODObject another_global_object3(
access_to_templated_non_pod()); // SIOF!
SomeOtherNonPODObject another_global_object4(42); // OK
int pod_accesses_non_pod = access_to_non_pod(); // SIOF!
struct X {
static int static_pod_accesses_non_pod;
};
int X::static_pod_accesses_non_pod = access_to_non_pod(); // SIOF!
SomeNonPODObject initWithStatic = getFunctionStaticNonPOD(); // OK
SomeNonPODObject initWithGlobal = getGlobalNonPOD(); // SIOF!

@ -1,19 +0,0 @@
/*
* 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.
*/
// This file exists only so that the SIOF checkers sees global_object
// being initialized via a method call. The SIOF checker could be
// improved to know that all non-POD types require initialization in
// C++.
struct SomeObject {
void some_method();
};
SomeObject global_object;

@ -0,0 +1,28 @@
/*
* 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.
*/
#include "siof_types.h"
SomeNonPODObject global_object2;
int access_to_non_pod() {
global_object2.some_method();
return 5;
}
SomeTemplatedNonPODObject<int> global_object3;
int access_to_templated_non_pod() { return global_object3.some_method(); }
SomeNonPODObject& getFunctionStaticNonPOD() {
static SomeNonPODObject instance;
return instance;
}
SomeNonPODObject& getGlobalNonPOD() { return global_object2; }

@ -0,0 +1,33 @@
/*
* 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.
*/
#include "siof_types.h"
extern SomeTemplatedNonPODObject<int> extern_global_object;
SomeTemplatedNonPODObject<int> global_object;
template <typename T>
struct SomeOtherTemplatedNonPODObject {
SomeOtherTemplatedNonPODObject() {
global_object.some_method(); // OK, same translation unit
extern_global_object.some_method(); // bad, different translation unit
};
SomeOtherTemplatedNonPODObject(int i) {
global_object.some_method(); // OK, same translation unit
};
};
SomeOtherTemplatedNonPODObject<bool> another_templated_global_object; // SIOF!
SomeOtherTemplatedNonPODObject<bool> another_templated_global_object2(
access_to_non_pod()); // SIOF!
SomeOtherTemplatedNonPODObject<bool> another_templated_global_object3(
access_to_templated_non_pod()); // SIOF!
SomeOtherTemplatedNonPODObject<bool> another_templated_global_object4(42); // OK

@ -7,15 +7,16 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
struct SomeObject { struct SomeNonPODObject {
void some_method(); virtual void some_method();
}; };
extern SomeObject global_object; template<typename T>
struct SomeTemplatedNonPODObject {
struct SomeOtherObject { virtual T some_method();
SomeOtherObject() { global_object.some_method(); };
}; };
// BAD: report SIOF here int access_to_templated_non_pod();
SomeOtherObject another_global_object; int access_to_non_pod();
SomeNonPODObject& getFunctionStaticNonPOD();
SomeNonPODObject& getGlobalNonPOD();

@ -1,6 +1,6 @@
/* @generated */ /* @generated */
digraph iCFG { digraph iCFG {
"__infer_globals_initializer_global.bdc08c089842ce08b974b22a75daf78e_3" [label="3: DeclStmt \n _fun_X_X(&#GB<globals/global_const1.cpp>$global:class X *) [line 13]\n " shape="box"] "__infer_globals_initializer_global.bdc08c089842ce08b974b22a75daf78e_3" [label="3: DeclStmt \n _fun_X_X(&#GB<globals/global_const1.cpp|!pod>$global:class X *) [line 13]\n " shape="box"]
"__infer_globals_initializer_global.bdc08c089842ce08b974b22a75daf78e_3" -> "__infer_globals_initializer_global.bdc08c089842ce08b974b22a75daf78e_2" ; "__infer_globals_initializer_global.bdc08c089842ce08b974b22a75daf78e_3" -> "__infer_globals_initializer_global.bdc08c089842ce08b974b22a75daf78e_2" ;
@ -18,7 +18,7 @@ digraph iCFG {
"X_X{_ZN1XC1ERKS_}.abc525d74d1815a6e1a874d1ed502de3_1" -> "X_X{_ZN1XC1ERKS_}.abc525d74d1815a6e1a874d1ed502de3_2" ; "X_X{_ZN1XC1ERKS_}.abc525d74d1815a6e1a874d1ed502de3_1" -> "X_X{_ZN1XC1ERKS_}.abc525d74d1815a6e1a874d1ed502de3_2" ;
"test{d41d8cd98f00b204e9800998ecf8427e_Z4testv}.8c08101fe48ee96867ff8578442d10bc_3" [label="3: Return Stmt \n n$0=*&__return_param:class X * [line 15]\n _fun_X_X(&#GB<globals/global_const1.cpp>$global:class X *) [line 13]\n _fun_X_X(n$0:class X *,&#GB<globals/global_const1.cpp>$global:class X &) [line 15]\n " shape="box"] "test{d41d8cd98f00b204e9800998ecf8427e_Z4testv}.8c08101fe48ee96867ff8578442d10bc_3" [label="3: Return Stmt \n n$0=*&__return_param:class X * [line 15]\n _fun_X_X(&#GB<globals/global_const1.cpp|!pod>$global:class X *) [line 13]\n _fun_X_X(n$0:class X *,&#GB<globals/global_const1.cpp|!pod>$global:class X &) [line 15]\n " shape="box"]
"test{d41d8cd98f00b204e9800998ecf8427e_Z4testv}.8c08101fe48ee96867ff8578442d10bc_3" -> "test{d41d8cd98f00b204e9800998ecf8427e_Z4testv}.8c08101fe48ee96867ff8578442d10bc_2" ; "test{d41d8cd98f00b204e9800998ecf8427e_Z4testv}.8c08101fe48ee96867ff8578442d10bc_3" -> "test{d41d8cd98f00b204e9800998ecf8427e_Z4testv}.8c08101fe48ee96867ff8578442d10bc_2" ;

@ -18,7 +18,7 @@ digraph iCFG {
"foo::Rectangle_Rectangle{_ZN3foo9RectangleC1Ev}.994e34698d49402781f481c8d7fa0e03_1" -> "foo::Rectangle_Rectangle{_ZN3foo9RectangleC1Ev}.994e34698d49402781f481c8d7fa0e03_2" ; "foo::Rectangle_Rectangle{_ZN3foo9RectangleC1Ev}.994e34698d49402781f481c8d7fa0e03_1" -> "foo::Rectangle_Rectangle{_ZN3foo9RectangleC1Ev}.994e34698d49402781f481c8d7fa0e03_2" ;
"__infer_globals_initializer_bar::rect.e5e9061ca63212fdc2fd329df6c073de_3" [label="3: DeclStmt \n _fun_bar::Rectangle_Rectangle(&#GB<shared/namespace/namespace.cpp>$bar::rect:class bar::Rectangle *) [line 38]\n " shape="box"] "__infer_globals_initializer_bar::rect.e5e9061ca63212fdc2fd329df6c073de_3" [label="3: DeclStmt \n _fun_bar::Rectangle_Rectangle(&#GB<shared/namespace/namespace.cpp|!pod>$bar::rect:class bar::Rectangle *) [line 38]\n " shape="box"]
"__infer_globals_initializer_bar::rect.e5e9061ca63212fdc2fd329df6c073de_3" -> "__infer_globals_initializer_bar::rect.e5e9061ca63212fdc2fd329df6c073de_2" ; "__infer_globals_initializer_bar::rect.e5e9061ca63212fdc2fd329df6c073de_3" -> "__infer_globals_initializer_bar::rect.e5e9061ca63212fdc2fd329df6c073de_2" ;

Loading…
Cancel
Save