#include <vector> std::vector<int> f() { std::vector<int> r; return r; } starting with gcc-8 ICEs using 'g++ -fcompare-debug=-Wnonnull' (as well as Wformat, Wrestrict, Wsuggest-attribute=format) cp/call.c:build_over_call() has: if (warn_nonnull || warn_format || warn_suggest_attribute_format || warn_restrict) { tree *fargs = (!nargs ? argarray : (tree *) alloca (nargs * sizeof (tree))); for (j = 0; j < nargs; j++) { /* For -Wformat undo the implicit passing by hidden reference done by convert_arg_to_ellipsis. */ if (TREE_CODE (argarray[j]) == ADDR_EXPR && TYPE_REF_P (TREE_TYPE (argarray[j]))) fargs[j] = TREE_OPERAND (argarray[j], 0); else fargs[j] = maybe_constant_value (argarray[j]); } warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn), nargs, fargs, NULL); } which if bypassed does not cause the ICE, which indicates that something in the snippet may affect code generation (not investigating further).
I think maybe_constant_value has a cache which may cause side-effects.
Confirmed (both the error and that maybe_constant_value has a cache). $ cat t.C && gcc -S -fcompare-debug=-Wrestrict t.C #include <vector> std::vector<int> f() { std::vector<int> r; return r; } xg++: error: t.C: -fcompare-debug failure
GCC 8.2 has been released.
I think the problem is not exactly that maybe_constant_value keeps a lookup cache, but rather that invoking maybe_constant_value may cause allocation of uids. So it wouldn't be enough to simply avoid populating the cache in warning context. It seems a bit strange to do full-blown constexpr evaluation for warnings, especially if normal compilation flow wouldn't perform the same evaluation. Wouldn't it make sense to use some more light-weight lookup for warning purposes? On this testcase we allocate a new uid via allocate_decl_uid () make_node (code=RESULT_DECL) build_decl (loc=13709891, code=RESULT_DECL, name=0x0, type=0x7ffff0d86e70) start_preparsed_function(tree_node*, tree_node*, int) () instantiate_decl(tree_node*, bool, bool) () instantiate_cx_fn_r (tp=0x7ffff0d88c98, walk_subtrees=0x7fffffffd528) walk_tree_1 walk_tree_1 walk_tree_1 walk_tree_without_duplicates_1 instantiate_constexpr_fns (t=0x7ffff0d88ea0) cxx_eval_outermost_constant_expr maybe_constant_value (t=0x7ffff0d88ea0, decl=0x0) build_over_call (cand=0x27a65a0, flags=1, complain=3) build_new_method_call_1 build_new_method_call build_special_member_call expand_aggr_init_1(tree_node*, tree_node*, tree_node*, tree_node*, int, int) () emit_mem_initializers(tree_node*) () tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) () tsubst_expr(tree_node*, tree_node*, int, tree_node*, bool) () instantiate_decl(tree_node*, bool, bool) () instantiate_pending_templates(int) () c_parse_final_cleanups() () compile_file() () toplev::main(int, char**) () main ()
(In reply to Alexander Monakov from comment #4) > It seems a bit strange to do full-blown constexpr evaluation for warnings, > especially if normal compilation flow wouldn't perform the same evaluation. If the warning might depend on a constant value, we try to come up with a constant value for it.
GCC 8.3 has been released.
Fixed for GCC 9 by the patch for PR 56856, which removed that call to maybe_constant_value. Not worth backporting.