Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

charmitro
Copy link
Contributor

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

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Dec 5, 2023
@llvmbot
Copy link
Member

llvmbot commented Dec 5, 2023

@llvm/pr-subscribers-clang

Author: Charalampos Mitrodimas (charmitro)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/74510.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+2-1)
  • (added) clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp (+20)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d768bb72e07c0..0850b2d64b632 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4952,7 +4952,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
         std::make_pair(Function, PointOfInstantiation));
     } else if (TSK == TSK_ImplicitInstantiation) {
       if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
-          !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) {
+          !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc()) &&
+          !Function->isVirtualAsWritten()) {
         Diag(PointOfInstantiation, diag::warn_func_template_missing)
           << Function;
         Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
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 0000000000000..7ae323343330e
--- /dev/null
+++ b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wundefined-func-template %s
+// expected-no-diagnostics
+
+namespace PR74016 {
+  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);
+  }
+};

Copy link
Contributor

@Fznamznon Fznamznon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps needs a release note.

@@ -4952,7 +4952,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
std::make_pair(Function, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
!getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) {
!getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc()) &&
!Function->isVirtualAsWritten()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check that it is pure? AFAIK isVirtualAsWritten returns true for function marked explicitly virtual. There is also FunctionDecl::isPure() to check that it is pure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

// RUN: %clang_cc1 -fsyntax-only -verify -Wundefined-func-template %s
// expected-no-diagnostics

namespace PR74016 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we normally call them GH when a bug was filed as a GitHub issue.

Suggested change
namespace PR74016 {
namespace GH74016 {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. I wasn't aware of this, thanks!

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from 0ea96c4 to 0be0d65 Compare December 5, 2023 19:52
@@ -4952,7 +4952,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
std::make_pair(Function, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
!getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) {
!getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc()) &&
!Function->isVirtualAsWritten() && !Function->isPure()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
!Function->isVirtualAsWritten() && !Function->isPure()) {
!(Function->isVirtualAsWritten() && Function->isPure()) {

Can you add a test to make sure non-pure virtual function still get diagnosed?

Copy link
Contributor Author

@charmitro charmitro Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After double-checking this, I think we should just check for !isPure() and don't bother checking for isVirtualAsWritten() at all since non-virtual functions cannot be pure. Also, for reference,

/// Whether this virtual function is pure, i.e. makes the containing class
/// abstract.
bool isPure() const { return FunctionDeclBits.IsPure; }

Code updated to match this. Also a test-case added to verify that non-pure virtual functions still get diagnosed.

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from 0be0d65 to 1140e00 Compare December 5, 2023 21:47
Copy link

github-actions bot commented Dec 5, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from 1140e00 to 5582cfa Compare December 5, 2023 21:53
@cor3ntin
Copy link
Contributor

cor3ntin commented Dec 6, 2023

Can you add a release note indicating #74016 was fixed?
Otherwise LGTM.

If you wanted to make a follow up {R to rename isPure to isPureVirtual, i think that might be helpful (to avoid confusion with the gnu::pure attribute)

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from 5582cfa to 83d29e8 Compare December 6, 2023 08:34
@charmitro
Copy link
Contributor Author

charmitro commented Dec 6, 2023

Thank you both for your review!

Perhaps needs a release note.

Can you add a release note indicating #74016 was fixed? Otherwise LGTM.

Release note added.

If you wanted to make a follow up {R to rename isPure to isPureVirtual, i think that might be helpful (to avoid confusion with the gnu::pure attribute)

Yes, this could be helpful. I'll create a follow up PR for this.

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

@ahatanak
Copy link
Collaborator

ahatanak commented Jan 5, 2024

Any progress on this patch?

As we discussed in #74016, we should make sure clang doesn't stop emitting the warning when the definition of a pure virtual function is actually needed.

It seems to me that we shouldn't set NeededForConstantEvaluation or NeedDefinition in Sema::MarkFunctionReferenced to true when a pure virtual function is used in a virtual function call.

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from e38ad9c to f60f12f Compare January 5, 2024 10:37
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from a minor NFC nit with where we decide to do the check, this LGTM

@@ -18931,7 +18931,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
// constant evaluated
bool NeededForConstantEvaluation =
isPotentiallyConstantEvaluatedContext(*this) &&
isImplicitlyDefinableConstexprFunction(Func);
isImplicitlyDefinableConstexprFunction(Func) && !Func->isPure();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how the function being pure relates to whether it's needed for constant evaluation. I think this should move down to NeedDefinition below?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I concur, this does not make sense doing the check here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving it to NeedDefinition silences the warnings of test call_pure_virtual_function_from_virtual, where we still require warnings for it, as mentioned in #74016 (comment).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure the diagnostic makes sense in that case since it can never actually be called.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank to @erichkeane I realized I am wrong, we can actually define a pure virtual function. So we do want to retain the diagnostic here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why moving it down silences the diagnostic, I would think doing (OdrUse == OdrUseContext::Used || NeededForConstantEvaluation || !Func->isPure()) should work.

Can you explain in more detail?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're actually right.

I don't really recall what I was entering back when I was developing it, but it should work now.

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from f60f12f to 7961a90 Compare March 23, 2024 11:49
Copy link

✅ With the latest revision this PR passed the Python code formatter.

@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from 7961a90 to 89eb978 Compare March 23, 2024 11:56
@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch 3 times, most recently from 958ba59 to c0ef5a0 Compare April 5, 2024 09:50
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 llvm#74016

Signed-off-by: Charalampos Mitrodimas <[email protected]>
@charmitro charmitro force-pushed the pure-virtual-function-missing-def branch from c0ef5a0 to 0348c13 Compare April 5, 2024 10:18
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Do you need someone to land this on your behalf?

@charmitro
Copy link
Contributor Author

LGTM! Do you need someone to land this on your behalf?

I don't have commit rights. If I remember correctly from when LLVM used Phabricator (reviews.llvm.org) you'd need my name & e-address. If that's so,
Charalampos Mitrodimas <[email protected]>

@AaronBallman AaronBallman merged commit 0c92f86 into llvm:main Apr 9, 2024
ahatanaka pushed a commit to swiftlang/llvm-project that referenced this pull request Apr 9, 2024
…lvm#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 llvm#74016

(cherry picked from commit 0c92f86)

Conflicts:
	clang/docs/ReleaseNotes.rst
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

-Wundefined-func-template warns that no definition is available for a pure virtual function
7 participants