https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113208
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at gcc dot gnu.org, | |ppalka at gcc dot gnu.org --- Comment #30 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, the difference is because we without/with constexpr we call on the abstract _ZN6vectorI12QualityValueEC4ERKS1_ at different times. Without it it is called from c_parse_final_cleanups -> instantiate_pending_templates -> instantiate_decl -> instantiate_body -> expand_or_defer_fn, so at_eof is true in 5071 if (DECL_INTERFACE_KNOWN (fn)) 5072 /* We've already made a decision as to how this function will 5073 be handled. */; 5074 else if (!at_eof 5075 || DECL_IMMEDIATE_FUNCTION_P (fn) 5076 || DECL_OMP_DECLARE_REDUCTION_P (fn)) 5077 tentative_decl_linkage (fn); 5078 else 5079 import_export_decl (fn); and so import_export_decl is called. Now import_export_decl sets 3512 else if (DECL_TEMPLOID_INSTANTIATION (decl)) 3513 { 3514 /* DECL is an implicit instantiation of a function or static 3515 data member. */ 3516 if (flag_implicit_templates 3517 || (flag_implicit_inline_templates 3518 && TREE_CODE (decl) == FUNCTION_DECL 3519 && DECL_DECLARED_INLINE_P (decl))) 3520 comdat_p = true; and because of comdat_p being true it does else if (comdat_p) { /* If we decided to put DECL in COMDAT, mark it accordingly at this point. */ comdat_linkage (decl); } which if (flag_weak) { make_decl_one_only (decl, cxx_comdat_group (decl)); Later on expand_or_defer_fn_1 calls maybe_clone_body. In that function because of the above DECL_ONE_ONLY (fn) is true, so we if (DECL_ONE_ONLY (fn)) cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone)); and later on alias = true; if (DECL_ONE_ONLY (fns[0])) { /* For comdat base and complete cdtors put them into the same, *[CD]5* comdat group instead of *[CD][12]*. */ Now, in the constexpr case, expand_or_defer_fn_1 is called much ealier, when not at_eof, during constant evaluation of a different synthetized constructor: #1 0x0000000000813795 in expand_or_defer_fn_1 (fn=<function_decl 0x7fffea2e0100 __ct >) at ../../gcc/cp/semantics.cc:5100 #2 0x0000000000813ac3 in expand_or_defer_fn (fn=<function_decl 0x7fffea2e0100 __ct >) at ../../gcc/cp/semantics.cc:5135 #3 0x00000000007c97a7 in instantiate_body (pattern=<template_decl 0x7ffff7ffa800 __ct >, args=<tree_vec 0x7fffea2df100>, d=<function_decl 0x7fffea2e0100 __ct >, nested_p=false) at ../../gcc/cp/pt.cc:27133 #4 0x00000000007cb08a in instantiate_decl (d=<function_decl 0x7fffea2e0100 __ct >, defer_ok=false, expl_inst_class_mem_p=false) at ../../gcc/cp/pt.cc:27399 #5 0x00000000004936da in cxx_eval_call_expression (ctx=0x7fffffffb120, t=<aggr_init_expr 0x7fffea2d7e00>, lval=vc_prvalue, non_constant_p=0x7fffffffb24f, overflow_p=0x7fffffffb24e) at ../../gcc/cp/constexpr.cc:3059 #6 0x00000000004a6319 in cxx_eval_constant_expression (ctx=0x7fffffffb120, t=<aggr_init_expr 0x7fffea2d7e00>, lval=vc_prvalue, non_constant_p=0x7fffffffb24f, overflow_p=0x7fffffffb24e, jump_target=0x0) at ../../gcc/cp/constexpr.cc:7532 #7 0x00000000004ac44e in cxx_eval_outermost_constant_expr (t=<call_expr 0x7fffea2d7dc0>, allow_non_constant=true, strict=true, manifestly_const_eval=mce_value::mce_false, constexpr_dtor=false, object=<indirect_ref 0x7fffea2dfbe0>) at ../../gcc/cp/constexpr.cc:8830 #8 0x00000000004ad558 in maybe_constant_value (t=<call_expr 0x7fffea2d7dc0>, decl=<tree 0x0>, manifestly_const_eval=mce_value::mce_false) at ../../gcc/cp/constexpr.cc:9118 #9 0x00000000004f90c7 in cp_fold (x=<call_expr 0x7fffea2d7dc0>, flags=3) at ../../gcc/cp/cp-gimplify.cc:3409 #10 0x00000000004ee8a1 in cp_fold_r (stmt_p=0x7fffea2df998, walk_subtrees=0x7fffffffb554, data_=0x7fffffffb5f0) at ../../gcc/cp/cp-gimplify.cc:1359 #11 0x0000000001552484 in walk_tree_1 (tp=0x7fffea2df998, func=0x4ee673 <cp_fold_r(tree*, int*, void*)>, data=0x7fffffffb5f0, pset=0x0, lh=0x859385 <cp_walk_subtrees(tree_node**, int*, tree_node* (*)(tree_node**, int*, void*), void*, hash_set<tree_node*, false, default_hash_traits<tree_node*> >*)>) at ../../gcc/tree.cc:11429 #12 0x00000000004ef1d0 in cp_fold_function (fndecl=<function_decl 0x7fffea2e4500 __ct >) at ../../gcc/cp/cp-gimplify.cc:1488 #13 0x000000000057cae5 in finish_function (inline_p=false) at ../../gcc/cp/decl.cc:18756 #14 0x0000000000624ec1 in synthesize_method (fndecl=<function_decl 0x7fffea2e4500 __ct >) at ../../gcc/cp/method.cc:1845 Because at_eof is false, we take the 5072 /* We've already made a decision as to how this function will 5073 be handled. */; 5074 else if (!at_eof 5075 || DECL_IMMEDIATE_FUNCTION_P (fn) 5076 || DECL_OMP_DECLARE_REDUCTION_P (fn)) 5077 tentative_decl_linkage (fn); path, so among other things don't define that the fn will be comdat. But still maybe_clone_body is called, but because DECL_ONE_ONLY (fn) is not true, the if (DECL_ONE_ONLY (fn)) cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone)); is not done, bool can_alias = can_alias_cdtor (fn); is also false because it has: /* Don't use aliases for weak/linkonce definitions unless we can put both symbols in the same COMDAT group. */ return (DECL_INTERFACE_KNOWN (fn) && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn)) && (!DECL_ONE_ONLY (fn) || (HAVE_COMDAT_GROUP && DECL_WEAK (fn)))); and DECL_INTERFACE_KNOWN (fn) is still false, and /* Tell cgraph if both ctors or both dtors are known to have the same body. */ if (can_alias && fns[0] && idx == 1 && cgraph_node::get_create (fns[0])->create_same_body_alias (clone, fns[0])) { alias = true; if (DECL_ONE_ONLY (fns[0])) { /* For comdat base and complete cdtors put them into the same, *[CD]5* comdat group instead of *[CD][12]*. */ isn't done either. Later on during c_parse_final_cleanups (aka at_eof) import_export_decl is called on the clones individually, because they were still deferred, but maybe_clone_body isn't called again (it really can't be) and nothing is able to redo the cdtor optimization at that point by turning one of the clones into an alias to the other one and adjusting the comdat group etc.