michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * Detects static initializers i.e. functions called during static initialization. michael@0: */ michael@0: michael@0: require({ after_gcc_pass: "cfg" }); michael@0: michael@0: function process_tree(fn) { michael@0: for each (let attr in translate_attributes(DECL_ATTRIBUTES(fn))) michael@0: if (attr.name == "constructor") michael@0: warning(pretty_func(fn) + " marked with constructor attribute\n"); michael@0: michael@0: if (decl_name_string(fn) != "__static_initialization_and_destruction_0") michael@0: return; michael@0: michael@0: let cfg = function_decl_cfg(fn); michael@0: for (let isn in cfg_isn_iterator(cfg)) { michael@0: if (isn.tree_code() != GIMPLE_CALL) michael@0: continue; michael@0: let decl = gimple_call_fndecl(isn); michael@0: let lhs = gimple_call_lhs(isn); michael@0: if (lhs) { michael@0: warning(pretty_var(lhs) + " defined by call to " + pretty_func(decl) + michael@0: " during static initialization", location_of(lhs)); michael@0: } else { michael@0: let arg = constructorArg(isn); michael@0: if (arg) michael@0: warning(pretty_var(arg) + " defined by call to constructor " + pretty_func(decl) + michael@0: " during static initialization", location_of(arg)); michael@0: else michael@0: warning(pretty_func(decl) + " called during static initialization", location_of(decl)); michael@0: } michael@0: } michael@0: } michael@0: michael@0: function constructorArg(call) { michael@0: let decl = gimple_call_fndecl(call); michael@0: michael@0: if (!DECL_CONSTRUCTOR_P(decl)) michael@0: return null; michael@0: michael@0: let arg = gimple_call_arg_iterator(call).next(); michael@0: if (TYPE_MAIN_VARIANT(TREE_TYPE(TREE_TYPE(arg))) != DECL_CONTEXT(decl)) michael@0: throw new Error("malformed constructor call?!"); michael@0: michael@0: return arg.tree_code() == ADDR_EXPR ? TREE_OPERAND(arg, 0) : arg; michael@0: } michael@0: michael@0: function pretty_func(fn) { michael@0: return rfunc_string(rectify_function_decl(fn)); michael@0: } michael@0: michael@0: function pretty_var(v) { michael@0: return type_string(TREE_TYPE(v)) + " " + expr_display(v); michael@0: }