Skip to content

Commit 0c92f86

Browse files
authored
[clang] Disable missing definition warning on pure virtual functions (#74510)
Warning '-Wundefined-func-template' incorrectly indicates that no definition is available for a pure virtual function. However, a definition is not needed for a pure virtual function. Fixes #74016
1 parent 1e44d9a commit 0c92f86

File tree

3 files changed

+75
-2
lines changed

3 files changed

+75
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,10 @@ Improvements to Clang's time-trace
353353

354354
Bug Fixes in This Version
355355
-------------------------
356+
- Clang's ``-Wundefined-func-template`` no longer warns on pure virtual
357+
functions.
358+
(`#74016 <https://github.com/llvm/llvm-project/issues/74016>`_)
359+
356360
- Fixed missing warnings when comparing mismatched enumeration constants
357361
in C (`#29217 <https://github.com/llvm/llvm-project/issues/29217>`).
358362

clang/lib/Sema/SemaExpr.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18982,8 +18982,10 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
1898218982
// Note that we skip the implicit instantiation of templates that are only
1898318983
// used in unused default arguments or by recursive calls to themselves.
1898418984
// This is formally non-conforming, but seems reasonable in practice.
18985-
bool NeedDefinition = !IsRecursiveCall && (OdrUse == OdrUseContext::Used ||
18986-
NeededForConstantEvaluation);
18985+
bool NeedDefinition =
18986+
!IsRecursiveCall &&
18987+
(OdrUse == OdrUseContext::Used ||
18988+
(NeededForConstantEvaluation && !Func->isPureVirtual()));
1898718989

1898818990
// C++14 [temp.expl.spec]p6:
1898918991
// If a template [...] is explicitly specialized then that specialization
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -Wundefined-func-template %s
2+
3+
namespace GH74016 {
4+
template <typename T> class B {
5+
public:
6+
constexpr void foo(const T &) { bar(1); }
7+
virtual constexpr void bar(unsigned int) = 0;
8+
};
9+
10+
template <typename T> class D : public B<T> {
11+
public:
12+
constexpr void bar(unsigned int) override {}
13+
};
14+
15+
void test() {
16+
auto t = D<int>();
17+
t.foo(0);
18+
}
19+
};
20+
21+
namespace call_pure_virtual_function_from_virtual {
22+
template <typename T> class B {
23+
public:
24+
const void foo(const T &) { B::bar(1); } // expected-warning {{instantiation of function 'call_pure_virtual_function_from_virtual::B<int>::bar' required here, but no definition is available}}
25+
// expected-note@-1 {{add an explicit instantiation declaration to suppress this warning if 'call_pure_virtual_function_from_virtual::B<int>::bar' is explicitly instantiated in another translation unit}}
26+
virtual const void bar(unsigned int) = 0; // expected-note {{forward declaration of template entity is here}}
27+
};
28+
29+
template <typename T> class D : public B<T> {
30+
public:
31+
const void bar(unsigned int) override {}
32+
};
33+
34+
void test() {
35+
auto t = D<int>();
36+
t.foo(0); // expected-note {{in instantiation of member function 'call_pure_virtual_function_from_virtual::B<int>::foo' requested here}}
37+
}
38+
};
39+
40+
namespace non_pure_virtual_function {
41+
template <typename T> class B {
42+
public:
43+
constexpr void foo(const T &) { bar(1); }
44+
45+
virtual constexpr void bar(unsigned int); // expected-warning {{inline function 'non_pure_virtual_function::B<int>::bar' is not defined}}
46+
// expected-note@-1 {{forward declaration of template entity is here}}
47+
// expected-note@-2 {{forward declaration of template entity is here}}
48+
// expected-note@-3 {{forward declaration of template entity is here}}
49+
};
50+
51+
template <typename T> class D : public B<T> { // expected-warning {{instantiation of function 'non_pure_virtual_function::B<int>::bar' required here, but no definition is available}}
52+
// expected-warning@-1 {{instantiation of function 'non_pure_virtual_function::B<int>::bar' required here, but no definition is available}}
53+
// expected-warning@-2 {{instantiation of function 'non_pure_virtual_function::B<int>::bar' required here, but no definition is available}}
54+
// expected-note@-3 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
55+
// expected-note@-4 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
56+
// expected-note@-5 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
57+
// expected-note@-6 {{used here}}
58+
59+
public:
60+
constexpr void bar(unsigned int) override { }
61+
};
62+
63+
void test() {
64+
auto t = D<int>();
65+
t.foo(0);
66+
}
67+
};

0 commit comments

Comments
 (0)