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.

Reply via email to