[clang] [clang] Disable missing definition warning on pure virtual functions (PR #74510)

Charalampos Mitrodimas via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 5 02:37:59 PST 2024


https://github.com/charmitro updated https://github.com/llvm/llvm-project/pull/74510

>From f60f12f8e4e8b70a8fdf2aa9398b94849a863fff Mon Sep 17 00:00:00 2001
From: Charalampos Mitrodimas <charmitro at posteo.net>
Date: Tue, 5 Dec 2023 11:46:56 +0200
Subject: [PATCH] [clang] Disable missing definition warning on pure virtual
 functions

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

Signed-off-by: Charalampos Mitrodimas <charmitro at posteo.net>
---
 clang/docs/ReleaseNotes.rst                   |  3 +
 clang/lib/Sema/SemaExpr.cpp                   |  2 +-
 .../instantiate-pure-virtual-function.cpp     | 67 +++++++++++++++++++
 3 files changed, 71 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ce7599ad34beaf..858248f3cce896 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -531,6 +531,9 @@ Improvements to Clang's time-trace
 
 Bug Fixes in This Version
 -------------------------
+- Clang's ``-Wundefined-func-template`` no longer warns on pure virtual
+  functions.
+  (`#74016 <https://github.com/llvm/llvm-project/issues/74016>`_)
 - Fixed an issue where a class template specialization whose declaration is
   instantiated in one module and whose definition is instantiated in another
   module may end up with members associated with the wrong declaration of the
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 960f513d1111b2..43b266ec07dd35 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18931,7 +18931,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
   //   constant evaluated
   bool NeededForConstantEvaluation =
       isPotentiallyConstantEvaluatedContext(*this) &&
-      isImplicitlyDefinableConstexprFunction(Func);
+      isImplicitlyDefinableConstexprFunction(Func) && !Func->isPure();
 
   // Determine whether we require a function definition to exist, per
   // C++11 [temp.inst]p3:
diff --git a/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
new file mode 100644
index 00000000000000..caec42b6b77f95
--- /dev/null
+++ b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wundefined-func-template %s
+
+namespace GH74016 {
+  template <typename T> class B {
+  public:
+    constexpr void foo(const T &) { bar(1); }
+    virtual constexpr void bar(unsigned int) = 0;
+  };
+
+  template <typename T> class D : public B<T> {
+  public:
+    constexpr void bar(unsigned int) override {}
+  };
+
+  void test() {
+    auto t = D<int>();
+    t.foo(0);
+  }
+};
+
+namespace call_pure_virtual_function_from_virtual {
+  template <typename T> class B {
+  public:
+    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}}
+    // expected-note at -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}}
+    virtual const void bar(unsigned int) = 0; // expected-note {{forward declaration of template entity is here}}
+  };
+
+  template <typename T> class D : public B<T> {
+  public:
+    const void bar(unsigned int) override {}
+  };
+
+  void test() {
+    auto t = D<int>();
+    t.foo(0); // expected-note {{in instantiation of member function 'call_pure_virtual_function_from_virtual::B<int>::foo' requested here}}
+  }
+};
+
+namespace non_pure_virtual_function {
+  template <typename T> class B {
+  public:
+    constexpr void foo(const T &) { bar(1); }
+
+    virtual constexpr void bar(unsigned int); // expected-warning {{inline function 'non_pure_virtual_function::B<int>::bar' is not defined}}
+    // expected-note at -1 {{forward declaration of template entity is here}}
+    // expected-note at -2 {{forward declaration of template entity is here}}
+    // expected-note at -3 {{forward declaration of template entity is here}}
+  };
+
+  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}}
+// expected-warning at -1 {{instantiation of function 'non_pure_virtual_function::B<int>::bar' required here, but no definition is available}}
+// expected-warning at -2 {{instantiation of function 'non_pure_virtual_function::B<int>::bar' required here, but no definition is available}}
+// expected-note at -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}}
+// expected-note at -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}}
+// expected-note at -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}}
+// expected-note at -6 {{used here}}
+
+  public:
+    constexpr void bar(unsigned int) override { }
+  };
+
+  void test() {
+    auto t = D<int>();
+    t.foo(0);
+  }
+};



More information about the cfe-commits mailing list