Bug 80916 - [7/8 Regression] Spurious "declared 'static' but never defined" warni
Summary: [7/8 Regression] Spurious "declared 'static' but never defined" warni
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.1.0
: P2 normal
Target Milestone: 7.5
Assignee: Jason Merrill
URL:
Keywords: diagnostic, patch
Depends on:
Blocks:
 
Reported: 2017-05-30 00:46 UTC by Davin McCall
Modified: 2019-03-07 15:16 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work: 5.5.0
Known to fail: 6.4.0, 7.2.0, 8.2.0, 9.0
Last reconfirmed: 2018-08-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Davin McCall 2017-05-30 00:46:36 UTC
The following code (reduced via creduce) gives a warning, when compiled with:
g++ -std=c++11 -Os -Wall -Wno-invalid-offsetof -c dinit-warn.cc

dinit-warn.cc:20:40: warning: 'void b::i< <template-parameter-1-1> >::dispatch(void*) [with <template-parameter-1-1> = {anonymous}::l]' declared 'static' but never defined [-Wunused-function]
 template <typename> class i : j { void dispatch(void *); };
                                        ^~~~~~~~

However, the highlighted function, "dispatch", is not declared 'static' (and indeed nothing in the code is declared static). Occurs at -Os and -O2, -O3, not at -O1/-O0.

--- begin ---
class a;
namespace b {
template <typename> class i;
class j {
  friend a;
  virtual void dispatch(void *);
};
}
class a {
  using d = b::j;

public:
  template <typename e> using c = b::i<e>;
  void f() {
    d *k = nullptr;
    k->dispatch(this);
  }
};
namespace b {
template <typename> class i : j { void dispatch(void *); };
}
using g = a;
g h;
namespace {
class l : g::c<l> {};
}
void m() { h.f(); }
--- end ---
Comment 1 Davin McCall 2017-05-30 23:43:16 UTC
(Does not actually require -Wno-invalid-offsetof to reproduce; that was just me copying my command line literally. Problem first appears in GCC 6.1, not in 5.x, still present in 7.1).
Comment 2 Martin Sebor 2017-11-27 20:23:13 UTC
Confirmed with GCC 8.0.
Comment 3 ensadc 2018-08-31 05:44:17 UTC
Reduced:

struct j {
  virtual void dispatch(void *);
};
template <typename>
struct i : j {
  void dispatch(void *);
};
namespace {
struct l : i<l> {};
}
void f(j *k) {
  k->dispatch(0);
}
Comment 4 Jonathan Wakely 2018-08-31 12:08:13 UTC
The warning started with r224161

    Merge debug-early branch into mainline.
Comment 5 Jakub Jelinek 2019-01-07 16:39:09 UTC
The wording could be improved, but why do you think the warning is spurious?

While the method isn't static, it is effectively static, because it is internal linkage (i.e. visibility constrained to the current TU in which it is not really defined).  If you ask for -Wunused-function, you get it if the compiler can figure it out.  The reason it doesn't warn at -O0 is that it doesn't see it unless it tries to devirtualize.

Not sure if we have a way to find out if !TREE_PUBLIC is because it has been declared static or because it has internal linkage and constrain_visibility VISIBILITY_ANON has been called on it (and would need a langhook anyway to determine that).
Comment 6 Davin McCall 2019-01-07 19:46:07 UTC
> The wording could be improved, but why do you think the warning is spurious?

I guess I think that the warning is spurious given the current wording? It may well be legitimate to warn that there is a declaration of a function with internal linkage but no definition, which may be what triggered this warning originally (it no longer triggers in my current code base, so I can't easily verify). But that's not what the warning does say.

If you'd prefer to change the title to reflect that the wording of the warning doesn't match its cause, I have no issue with that.
Comment 7 ensadc 2019-01-08 11:27:52 UTC
Note that the "never defined" part is also misleading: the warning persists when `i::dispatch` does have a definition (https://wandbox.org/permlink/MKif1shXFjt7aT6C):

struct j {
  virtual void dispatch(void *) {}
};
template <typename>
struct i : j {
  void dispatch(void *) {} // warning: 'void i< <template-parameter-1-1> >::dispatch(void*) [with <template-parameter-1-1> = {anonymous}::l]' declared 'static' but never defined [-Wunused-function]
};
namespace {
struct l : i<l> {};
}
void f(j *k) {
  k->dispatch(0);
}
Comment 8 Davin McCall 2019-01-08 21:45:23 UTC
(In reply to ensadc from comment #7)
> Note that the "never defined" part is also misleading: the warning persists
> when `i::dispatch` does have a definition

Yes; and actually, I note that in the original test case I supplied, the dispatch function doesn't have a definition, but it doesn't have internal linkage either.

So, I think the warning really is spurious and it's not just a case of it saying "declared static" where it should say "has internal linkage".
Comment 9 Jason Merrill 2019-01-25 14:12:07 UTC
It has internal linkage because one of its template arguments is a local class, and it isn't instantiated because it isn't ever used.  It's added to cgraph as a possible devirtualization target.

I think the last of these is the place to attack this issue, since it's also the source of the regression.
Comment 10 Jason Merrill 2019-01-27 20:33:46 UTC
Patch posted: https://gcc.gnu.org/ml/gcc-patches/2019-01/msg01512.html
Comment 11 Jason Merrill 2019-02-27 18:47:57 UTC
Patch still waiting for review.
Comment 12 Jason Merrill 2019-03-07 15:10:57 UTC
Author: jason
Date: Thu Mar  7 15:10:22 2019
New Revision: 269459

URL: https://gcc.gnu.org/viewcvs?rev=269459&root=gcc&view=rev
Log:
	PR c++/80916 - spurious "static but not defined" warning.

Nothing can refer to an internal decl with no definition, so we shouldn't
treat such a decl as a possible devirtualization target.

	* gimple-fold.c (can_refer_decl_in_current_unit_p): Return false
	for an internal symbol with DECL_EXTERNAL.

Added:
    trunk/gcc/testsuite/g++.dg/warn/unused-fn1.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/gimple-fold.c
Comment 13 Jason Merrill 2019-03-07 15:16:36 UTC
Fixed on trunk so far.