[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-21 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #10 from GCC Commits  ---
The trunk branch has been updated by Marek Polacek :

https://gcc.gnu.org/g:081f8937cb82da311c224da04b0c6cbd57a8fb5d

commit r14-9596-g081f8937cb82da311c224da04b0c6cbd57a8fb5d
Author: Marek Polacek 
Date:   Thu Mar 7 20:41:23 2024 -0500

c++: explicit inst of template method not generated [PR110323]

Consider

  constexpr int VAL = 1;
  struct foo {
  template 
  void bar(typename std::conditional::type arg) { }
  };
  template void foo::bar<1>(int arg);

where we since r11-291 fail to emit the code for the explicit
instantiation.  That's because cp_walk_subtrees/TYPENAME_TYPE now
walks TYPE_CONTEXT ('conditional' here) as well, and in a template
finds the B==VAL template argument.  VAL is constexpr, which implies const,
which in the global scope implies static. 
constrain_visibility_for_template
then makes "struct conditional<(B == VAL), int, float>" non-TREE_PUBLIC.
Then symtab_node::needed_p checks TREE_PUBLIC, sees it's 0, and we don't
emit any code.

I thought the fix would be some ODR-esque check to not consider
constexpr variables/fns that are used just for their value.  But
it turned out to be tricky.  For instance, we can't skip
determine_visibility in a template; we can't even skip it for value-dep
expressions.  For example, no-linkage-expr1.C has

  using P = struct {}*;
  template 
  void f(int(*)[((P)0, N)]) {}

where ((P)0, N) is value-dep, but N is not relevant here: we have to
ferret out the anonymous type.  When instantiating, it's already gone.

This patch uses decl_constant_var_p.  This is to implement (an
approximation) [basic.def.odr]#14.5.1 and [basic.def.odr]#5.2.

PR c++/110323

gcc/cp/ChangeLog:

* decl2.cc (min_vis_expr_r) : Do nothing for
decl_constant_var_p VAR_DECLs.

gcc/testsuite/ChangeLog:

* g++.dg/template/explicit-instantiation6.C: New test.
* g++.dg/template/explicit-instantiation7.C: New test.

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-08 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #9 from Marek Polacek  ---
Oh and I meant to say it's the DECL_DECLARED_INLINE_P check that makes the
difference.

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-08 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #8 from Marek Polacek  ---
(In reply to Patrick Palka from comment #7)
> I noticed we emit the function if we turn it into a non-member:
> 
> #include 
> 
> constexpr int VAL = 1;
> 
> template 
> void bar(typename std::conditional::type arg) {
> }
> 
> template void bar<1>(int arg);
> 
> I wonder why this bug seems specific to member functions?

Good question.  It's because in this case bar is marked as force_output here:

  /* When not optimizing, also output the static functions. (see
 PR24561), but don't do so for always_inline functions, functions
 declared inline and nested functions.  These were optimized out
 in the original implementation and it is unclear whether we want
 to change the behavior here.  */
  if (((!opt_for_fn (decl, optimize) || flag_keep_static_functions
|| node->no_reorder)
   && !node->cpp_implicit_alias
   && !DECL_DISREGARD_INLINE_LIMITS (decl)
   && !DECL_DECLARED_INLINE_P (decl)
   && !(DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
  && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
node->force_output = 1;

and when deciding if we ought to emit the fn in symtab_node::needed_p we do:

  /* If the user told us it is used, then it must be so.  */
  if (force_output)
return true;


With -O the fn isn't emitted.

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-08 Thread ppalka at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

Patrick Palka  changed:

   What|Removed |Added

 CC||ppalka at gcc dot gnu.org

--- Comment #7 from Patrick Palka  ---
I noticed we emit the function if we turn it into a non-member:

#include 

constexpr int VAL = 1;

template 
void bar(typename std::conditional::type arg) {
}

template void bar<1>(int arg);

I wonder why this bug seems specific to member functions?

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-07 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #6 from Marek Polacek  ---
Extended test.  I think all 4 should be emitted.

```
// PR c++/110323

template
struct conditional { using type = T; };

template
struct conditional { using type = F; };

constexpr int VAL = 1;

static constexpr int getval () { return 1; }

template
constexpr int TVAL = 1;

static struct S {
  constexpr operator bool() { return true; }
} s;

struct foo {
template 
void bar(typename conditional::type arg) { }

template 
void baz(typename conditional::type arg) { }

template 
void qux(typename conditional, int, float>::type arg) { }

template 
void lox(typename conditional::type arg) { }
};

template void foo::bar<1>(int arg);
template void foo::baz<1>(int arg);
template void foo::qux<1>(int arg);
template void foo::lox<1>(int arg);
```

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-06 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

Marek Polacek  changed:

   What|Removed |Added

 Status|NEW |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |mpolacek at gcc dot 
gnu.org

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-05 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #5 from Marek Polacek  ---
VAL is constexpr, which implies const, which in the global scope implies
static.  Then constrain_visibility_for_template makes "struct conditional<(B ==
VAL), int, float>" non-TREE_PUBLIC.  So with

  extern constexpr int VAL = 1;

the test works again.

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-05 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #4 from Marek Polacek  ---
Ah -- if we walk into TYPE_CONTEXT (t) (here: struct conditional), then in
min_vis_r we determine the visibility as VISIBILITY_ANON.  Without it, it
remains VISIBILITY_DEFAULT.

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-05 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

--- Comment #3 from Marek Polacek  ---
This makes a difference for some reason:

--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5542,7 +5542,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p,
walk_tree_fn func,
   break;

 case TYPENAME_TYPE:
-  WALK_SUBTREE (TYPE_CONTEXT (t));
+  //WALK_SUBTREE (TYPE_CONTEXT (t));
   WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t));
   *walk_subtrees_p = 0;
   break;

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2024-03-05 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

Marek Polacek  changed:

   What|Removed |Added

   Priority|P3  |P2
 CC||mpolacek at gcc dot gnu.org

--- Comment #2 from Marek Polacek  ---
Started with r11-291-g0f50f6daa14018:

commit 0f50f6daa140186a048cbf33f54f4591eabf5f12
Author: Jason Merrill 
Date:   Mon May 11 15:46:59 2020 -0400

c++: tree walk into TYPENAME_TYPE.

```
template
struct conditional { using type = T; };

template
struct conditional { using type = F; };

constexpr int VAL = 1;

struct foo {
template 
void bar(typename conditional::type arg) {
}
};

template void foo::bar<1>(int arg);
```

[Bug c++/110323] [11/12/13/14 Regression] Code for explicit instantiation of template method of template class not generated

2023-06-20 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110323

Andrew Pinski  changed:

   What|Removed |Added

   Keywords||wrong-code
   Target Milestone|--- |11.5
Summary|Code for explicit   |[11/12/13/14 Regression]
   |instantiation of template   |Code for explicit
   |method of template class|instantiation of template
   |not generated   |method of template class
   ||not generated
 Ever confirmed|0   |1
   Last reconfirmed||2023-06-20
 Status|UNCONFIRMED |NEW
URL|https://godbolt.org/z/x4ao4 |
   |dxdx|
  Known to work|10.4.0  |10.1.0, 9.1.0

--- Comment #1 from Andrew Pinski  ---
Confirmed.