[clang-tools-extra] [clang-tidy] Portability Template Virtual Member Function Check (PR #110099)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 7 17:51:39 PDT 2024
https://github.com/isuckatcs updated https://github.com/llvm/llvm-project/pull/110099
>From 570ce88b1e5a3839eca8adf4f567fc7547b6f661 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 26 Sep 2024 11:43:10 +0200
Subject: [PATCH 1/7] [clang-tidy] Portability Template Virtual Member Function
Check
---
.../clang-tidy/portability/CMakeLists.txt | 1 +
.../portability/PortabilityTidyModule.cpp | 3 +
.../TemplateVirtualMemberFunctionCheck.cpp | 49 +++++++
.../TemplateVirtualMemberFunctionCheck.h | 36 +++++
clang-tools-extra/docs/ReleaseNotes.rst | 7 +
.../docs/clang-tidy/checks/list.rst | 1 +
.../template-virtual-member-function.rst | 33 +++++
.../template-virtual-member-function.cpp | 134 ++++++++++++++++++
8 files changed, 264 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
diff --git a/clang-tools-extra/clang-tidy/portability/CMakeLists.txt b/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
index 01a86d686daa76..df08cf2c8e292c 100644
--- a/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
@@ -9,6 +9,7 @@ add_clang_library(clangTidyPortabilityModule
RestrictSystemIncludesCheck.cpp
SIMDIntrinsicsCheck.cpp
StdAllocatorConstCheck.cpp
+ TemplateVirtualMemberFunctionCheck.cpp
LINK_LIBS
clangTidy
diff --git a/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
index b3759a754587d7..316b98b46cf3f2 100644
--- a/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
@@ -12,6 +12,7 @@
#include "RestrictSystemIncludesCheck.h"
#include "SIMDIntrinsicsCheck.h"
#include "StdAllocatorConstCheck.h"
+#include "TemplateVirtualMemberFunctionCheck.h"
namespace clang::tidy {
namespace portability {
@@ -25,6 +26,8 @@ class PortabilityModule : public ClangTidyModule {
"portability-simd-intrinsics");
CheckFactories.registerCheck<StdAllocatorConstCheck>(
"portability-std-allocator-const");
+ CheckFactories.registerCheck<TemplateVirtualMemberFunctionCheck>(
+ "portability-template-virtual-member-function");
}
};
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
new file mode 100644
index 00000000000000..6b7b50798798fa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
@@ -0,0 +1,49 @@
+//===--- TemplateVirtualMemberFunctionCheck.cpp - clang-tidy
+//-------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TemplateVirtualMemberFunctionCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::portability {
+
+void TemplateVirtualMemberFunctionCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(classTemplateSpecializationDecl().bind("specialization"),
+ this);
+}
+
+void TemplateVirtualMemberFunctionCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *MatchedDecl =
+ Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
+
+ if (MatchedDecl->isExplicitSpecialization())
+ return;
+
+ for (auto &&Method : MatchedDecl->methods()) {
+ if (!Method->isVirtual())
+ continue;
+
+ if (const auto *Dtor = llvm::dyn_cast<CXXDestructorDecl>(Method);
+ Dtor && Dtor->isDefaulted())
+ continue;
+
+ if (!Method->isUsed()) {
+ diag(Method->getLocation(),
+ "unspecified virtual member function instantiation; the virtual "
+ "member function is not instantiated but it might be with a "
+ "different compiler");
+ diag(MatchedDecl->getPointOfInstantiation(), "template instantiated here",
+ DiagnosticIDs::Note);
+ }
+ }
+}
+
+} // namespace clang::tidy::portability
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h
new file mode 100644
index 00000000000000..9d7918dbdba612
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h
@@ -0,0 +1,36 @@
+//===--- TemplateVirtualMemberFunctionCheck.h - clang-tidy ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_TEMPLATEVIRTUALMEMBERFUNCTIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_TEMPLATEVIRTUALMEMBERFUNCTIONCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::portability {
+
+/// Detects C++ [temp.inst#11]: "It is unspecified whether or not an
+/// implementation implicitly instantiates a virtual member function of a class
+/// template if the virtual member function would not otherwise be
+/// instantiated."
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/portability/template-virtual-member-function.html
+class TemplateVirtualMemberFunctionCheck : public ClangTidyCheck {
+public:
+ TemplateVirtualMemberFunctionCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+};
+
+} // namespace clang::tidy::portability
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_TEMPLATEVIRTUALMEMBERFUNCTIONCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3e051c7db6adcc..ab44c9a5ead9f6 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -121,6 +121,13 @@ New checks
Gives warnings for tagged unions, where the number of tags is
different from the number of data members inside the union.
+- New :doc:`portability-template-virtual-member-function
+ <clang-tidy/checks/portability/template-virtual-member-function>` check.
+
+ Detects C++ [temp.inst#11]: "It is unspecified whether or not an implementation
+ implicitly instantiates a virtual member function of a class template if the
+ virtual member function would not otherwise be instantiated."
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index d76466d480d39c..0082234f5ed31b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -348,6 +348,7 @@ Clang-Tidy Checks
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
+ :doc:`portability-template-virtual-member-function <portability/template-virtual-member-function>`,
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
new file mode 100644
index 00000000000000..3e22d967734fa1
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
@@ -0,0 +1,33 @@
+.. title:: clang-tidy - portability-template-virtual-member-function
+
+portability-template-virtual-member-function
+============================================
+Per C++ ``[temp.inst#11]``: "It is unspecified whether or not an implementation
+implicitly instantiates a virtual member function of a class template if the virtual
+member function would not otherwise be instantiated."
+
+In the following snippets the virtual member function is not instantiated by gcc and clang,
+but it is instantiated by MSVC, so while the snippet is accepted by the former compilers,
+it is rejected by the latter.
+
+.. code:: c++
+
+ template<typename T>
+ struct CrossPlatformError {
+ virtual ~CrossPlatformError() = default;
+
+ static void used() {}
+
+ virtual void unused() {
+ T MSVCError = this;
+ };
+ };
+
+ int main() {
+ CrossPlatformError<int>::used();
+ return 0;
+ }
+
+Cross-platform projects that need to support MSVC on Windows might see compiler errors
+because certain virtual member functions are instantiated, which are not instantiated
+by other compilers on other platforms. This check highlights such virtual member functions.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
new file mode 100644
index 00000000000000..59503e46b9bf3f
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
@@ -0,0 +1,134 @@
+// RUN: %check_clang_tidy %s portability-template-virtual-member-function %t
+namespace UninstantiatedVirtualMember {
+template<typename T>
+struct CrossPlatformError {
+ virtual ~CrossPlatformError() = default;
+
+ static void used() {}
+
+ // CHECK-MESSAGES: [[#@LINE+1]]:18: warning: unspecified virtual member function instantiation
+ virtual void unused() {
+ T MSVCError = this;
+ };
+};
+
+int main() {
+ // CHECK-MESSAGES: [[#@LINE+1]]:5: note: template instantiated here
+ CrossPlatformError<int>::used();
+ return 0;
+}
+} // namespace UninstantiatedVirtualMember
+
+namespace UninstantiatedVirtualMembers {
+template<typename T>
+struct CrossPlatformError {
+ virtual ~CrossPlatformError() = default;
+
+ static void used() {}
+
+ // CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
+ // CHECK-MESSAGES: [[#@LINE+13]]:5: note: template instantiated here
+ virtual void unused() {
+ T MSVCError = this;
+ };
+
+ // CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
+ // CHECK-MESSAGES: [[#@LINE+7]]:5: note: template instantiated here
+ virtual void unused2() {
+ T MSVCError = this;
+ };
+};
+
+int main() {
+ CrossPlatformError<int>::used();
+ return 0;
+}
+} // namespace UninstantiatedVirtualMembers
+
+namespace UninstantiatedVirtualDestructor {
+template<typename T>
+struct CrossPlatformError {
+ // CHECK-MESSAGES: [[#@LINE+2]]:13: warning: unspecified virtual member function instantiation
+ // CHECK-MESSAGES: [[#@LINE+9]]:5: note: template instantiated here
+ virtual ~CrossPlatformError() {
+ T MSVCError = this;
+ };
+
+ static void used() {}
+};
+
+int main() {
+ CrossPlatformError<int>::used();
+ return 0;
+}
+} // namespace UninstantiatedVirtualDestructor
+
+namespace MultipleImplicitInstantiations {
+template<typename T>
+struct CrossPlatformError {
+ virtual ~CrossPlatformError() = default;
+
+ static void used() {}
+
+ // CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
+ // CHECK-MESSAGES: [[#@LINE+7]]:5: note: template instantiated here
+ virtual void unused() {
+ T MSVCError = this;
+ };
+};
+
+int main() {
+ CrossPlatformError<int>::used();
+ CrossPlatformError<float>::used();
+ CrossPlatformError<long>::used();
+ return 0;
+}
+} // namespace MultipleImplicitInstantiations
+
+namespace SomeImplicitInstantiationError {
+template <typename T> struct CrossPlatformError {
+ virtual ~CrossPlatformError() = default;
+
+ static void used() {}
+
+ // CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
+ // CHECK-MESSAGES: [[#@LINE+5]]:5: note: template instantiated here
+ virtual void unused(){};
+};
+
+int main() {
+ CrossPlatformError<int>::used();
+ CrossPlatformError<float> NoError;
+ return 0;
+}
+} // namespace SomeImplicitInstantiationError
+
+namespace InstantiatedVirtualMemberFunctions {
+template<typename T>
+struct NoError {
+ virtual ~NoError() {};
+ virtual void unused() {};
+ virtual void unused2() {};
+ virtual void unused3() {};
+};
+
+int main() {
+ NoError<int> Ne;
+ return 0;
+}
+} // namespace InstantiatedVirtualMemberFunctions
+
+namespace UninstantiatedNonVirtualMemberFunctions {
+template<typename T>
+struct NoError {
+ static void used() {};
+ void unused() {};
+ void unused2() {};
+ void unused3() {};
+};
+
+int main() {
+ NoError<int>::used();
+ return 0;
+}
+} // namespace UninstantiatedNonVirtualMemberFunctions
>From cf3cb22c667adc1fa095d7e6e43af4ed33f523c0 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Thu, 26 Sep 2024 20:09:16 +0200
Subject: [PATCH 2/7] address comments
---
.../TemplateVirtualMemberFunctionCheck.cpp | 3 +--
clang-tools-extra/docs/ReleaseNotes.rst | 8 +++++---
.../portability/template-virtual-member-function.rst | 11 +++++++----
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
index 6b7b50798798fa..e97c32ba46ed27 100644
--- a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
@@ -1,5 +1,4 @@
-//===--- TemplateVirtualMemberFunctionCheck.cpp - clang-tidy
-//-------------------===//
+//===--- TemplateVirtualMemberFunctionCheck.cpp - clang-tidy --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index ab44c9a5ead9f6..7a7eccab4f3ea4 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -124,9 +124,11 @@ New checks
- New :doc:`portability-template-virtual-member-function
<clang-tidy/checks/portability/template-virtual-member-function>` check.
- Detects C++ [temp.inst#11]: "It is unspecified whether or not an implementation
- implicitly instantiates a virtual member function of a class template if the
- virtual member function would not otherwise be instantiated."
+ Upon instantiating a template class, non-virtual member functions don't have
+ to be instantiated unless they are used. Virtual member function instantiation
+ on the other hand is unspecified and depends on the implementation of the compiler.
+ This check intends to find cases when a virtual member function is not instantiated
+ but it might be with a different compiler.
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
index 3e22d967734fa1..084488a68ea82e 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
@@ -2,11 +2,14 @@
portability-template-virtual-member-function
============================================
-Per C++ ``[temp.inst#11]``: "It is unspecified whether or not an implementation
-implicitly instantiates a virtual member function of a class template if the virtual
-member function would not otherwise be instantiated."
-In the following snippets the virtual member function is not instantiated by gcc and clang,
+Upon instantiating a template class, non-virtual member functions don't have to be
+instantiated unless they are used. Virtual member function instantiation on the other hand
+is unspecified and depends on the implementation of the compiler. This check intends to find
+cases when a virtual member function is not instantiated but it might be with a different
+compiler.
+
+In the following snippets the virtual member function is not instantiated by GCC and Clang,
but it is instantiated by MSVC, so while the snippet is accepted by the former compilers,
it is rejected by the latter.
>From 838ee487024075edf0578a45ba9e8b6644fd3a6a Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Fri, 27 Sep 2024 01:57:00 +0200
Subject: [PATCH 3/7] address comments
---
.../TemplateVirtualMemberFunctionCheck.cpp | 9 ++---
.../TemplateVirtualMemberFunctionCheck.h | 10 +++--
.../template-virtual-member-function.cpp | 39 +++++++++++++++++++
3 files changed, 49 insertions(+), 9 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
index e97c32ba46ed27..80e59a2f0e596a 100644
--- a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
@@ -14,7 +14,9 @@ using namespace clang::ast_matchers;
namespace clang::tidy::portability {
void TemplateVirtualMemberFunctionCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(classTemplateSpecializationDecl().bind("specialization"),
+ Finder->addMatcher(classTemplateSpecializationDecl(
+ unless(isExplicitTemplateSpecialization()))
+ .bind("specialization"),
this);
}
@@ -23,10 +25,7 @@ void TemplateVirtualMemberFunctionCheck::check(
const auto *MatchedDecl =
Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
- if (MatchedDecl->isExplicitSpecialization())
- return;
-
- for (auto &&Method : MatchedDecl->methods()) {
+ for (const CXXMethodDecl *Method : MatchedDecl->methods()) {
if (!Method->isVirtual())
continue;
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h
index 9d7918dbdba612..41f92adadd6e8a 100644
--- a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.h
@@ -13,10 +13,12 @@
namespace clang::tidy::portability {
-/// Detects C++ [temp.inst#11]: "It is unspecified whether or not an
-/// implementation implicitly instantiates a virtual member function of a class
-/// template if the virtual member function would not otherwise be
-/// instantiated."
+/// Upon instantiating a template class, non-virtual member functions don't have
+/// to be instantiated unless they are used. Virtual member function
+/// instantiation on the other hand is unspecified and depends on the
+/// implementation of the compiler. This check intends to find cases when a
+/// virtual member function is not instantiated but it might be with a different
+/// compiler.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/portability/template-virtual-member-function.html
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
index 59503e46b9bf3f..94786ae93dd3f3 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/template-virtual-member-function.cpp
@@ -132,3 +132,42 @@ int main() {
return 0;
}
} // namespace UninstantiatedNonVirtualMemberFunctions
+
+namespace PartialSpecializationError {
+template<typename T, typename U>
+struct CrossPlatformError {};
+
+template<typename U>
+struct CrossPlatformError<int, U>{
+ virtual ~CrossPlatformError() = default;
+
+ static void used() {}
+
+ // CHECK-MESSAGES: [[#@LINE+2]]:18: warning: unspecified virtual member function instantiation
+ // CHECK-MESSAGES: [[#@LINE+7]]:5: note: template instantiated here
+ virtual void unused() {
+ U MSVCError = this;
+ };
+};
+
+int main() {
+ CrossPlatformError<int, float>::used();
+ return 0;
+}
+} // namespace PartialSpecializationError
+
+namespace PartialSpecializationNoInstantiation {
+template<typename T, typename U>
+struct NoInstantiation {};
+
+template<typename U>
+struct NoInstantiation<int, U>{
+ virtual ~NoInstantiation() = default;
+
+ static void used() {}
+
+ virtual void unused() {
+ U MSVCError = this;
+ };
+};
+} // namespace PartialSpecializationNoInstantiation
>From 2ecd43d96bf9a81641dd116a2569c57b959b5612 Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Fri, 27 Sep 2024 02:42:49 +0200
Subject: [PATCH 4/7] using matchers
---
.../TemplateVirtualMemberFunctionCheck.cpp | 44 +++++++++----------
1 file changed, 21 insertions(+), 23 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
index 80e59a2f0e596a..79e002d8b945c5 100644
--- a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
@@ -12,36 +12,34 @@
using namespace clang::ast_matchers;
namespace clang::tidy::portability {
+namespace {
+AST_MATCHER(CXXMethodDecl, isUsed) { return Node.isUsed(); }
+} // namespace
void TemplateVirtualMemberFunctionCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(classTemplateSpecializationDecl(
- unless(isExplicitTemplateSpecialization()))
- .bind("specialization"),
- this);
+ Finder->addMatcher(
+ cxxMethodDecl(
+ allOf(ofClass(classTemplateSpecializationDecl(
+ unless(isExplicitTemplateSpecialization()))
+ .bind("specialization")),
+ isVirtual(), unless(isUsed()),
+ unless(cxxDestructorDecl(isDefaulted()))))
+ .bind("method"),
+ this);
}
void TemplateVirtualMemberFunctionCheck::check(
const MatchFinder::MatchResult &Result) {
- const auto *MatchedDecl =
+ const auto *ImplicitSpecialization =
Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
-
- for (const CXXMethodDecl *Method : MatchedDecl->methods()) {
- if (!Method->isVirtual())
- continue;
-
- if (const auto *Dtor = llvm::dyn_cast<CXXDestructorDecl>(Method);
- Dtor && Dtor->isDefaulted())
- continue;
-
- if (!Method->isUsed()) {
- diag(Method->getLocation(),
- "unspecified virtual member function instantiation; the virtual "
- "member function is not instantiated but it might be with a "
- "different compiler");
- diag(MatchedDecl->getPointOfInstantiation(), "template instantiated here",
- DiagnosticIDs::Note);
- }
- }
+ const auto *MethodDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
+
+ diag(MethodDecl->getLocation(),
+ "unspecified virtual member function instantiation; the virtual "
+ "member function is not instantiated but it might be with a "
+ "different compiler");
+ diag(ImplicitSpecialization->getPointOfInstantiation(),
+ "template instantiated here", DiagnosticIDs::Note);
}
} // namespace clang::tidy::portability
>From b575d5d35b1d0f4a56059b754bd64caba8d1222d Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Fri, 27 Sep 2024 02:48:07 +0200
Subject: [PATCH 5/7] address comments
---
.../TemplateVirtualMemberFunctionCheck.cpp | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
index 79e002d8b945c5..9c2f27f01f1849 100644
--- a/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/TemplateVirtualMemberFunctionCheck.cpp
@@ -18,12 +18,11 @@ AST_MATCHER(CXXMethodDecl, isUsed) { return Node.isUsed(); }
void TemplateVirtualMemberFunctionCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- cxxMethodDecl(
- allOf(ofClass(classTemplateSpecializationDecl(
- unless(isExplicitTemplateSpecialization()))
- .bind("specialization")),
- isVirtual(), unless(isUsed()),
- unless(cxxDestructorDecl(isDefaulted()))))
+ cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
+ unless(isExplicitTemplateSpecialization()))
+ .bind("specialization")),
+ isVirtual(), unless(isUsed()),
+ unless(cxxDestructorDecl(isDefaulted())))
.bind("method"),
this);
}
>From 9f78992562f7b029704b1e7d94792f5a84803cde Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Fri, 27 Sep 2024 02:55:18 +0200
Subject: [PATCH 6/7] addressed comments
---
clang-tools-extra/docs/ReleaseNotes.rst | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 7a7eccab4f3ea4..8e04e9223035c7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -124,11 +124,8 @@ New checks
- New :doc:`portability-template-virtual-member-function
<clang-tidy/checks/portability/template-virtual-member-function>` check.
- Upon instantiating a template class, non-virtual member functions don't have
- to be instantiated unless they are used. Virtual member function instantiation
- on the other hand is unspecified and depends on the implementation of the compiler.
- This check intends to find cases when a virtual member function is not instantiated
- but it might be with a different compiler.
+ Finds cases when an uninstantiated virtual member function in a template class
+ causes cross-compiler incompatibility.
New check aliases
^^^^^^^^^^^^^^^^^
>From 7fd57a46c2478d9707c2f96700cb6aedc14c687a Mon Sep 17 00:00:00 2001
From: isuckatcs <65320245+isuckatcs at users.noreply.github.com>
Date: Fri, 27 Sep 2024 15:44:29 +0200
Subject: [PATCH 7/7] addressed comments
---
.../portability/template-virtual-member-function.rst | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
index 084488a68ea82e..aa3ed6653b475b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst
@@ -3,11 +3,12 @@
portability-template-virtual-member-function
============================================
+Finds cases when an uninstantiated virtual member function in a template class causes
+cross-compiler incompatibility.
+
Upon instantiating a template class, non-virtual member functions don't have to be
instantiated unless they are used. Virtual member function instantiation on the other hand
-is unspecified and depends on the implementation of the compiler. This check intends to find
-cases when a virtual member function is not instantiated but it might be with a different
-compiler.
+is unspecified and depends on the implementation of the compiler.
In the following snippets the virtual member function is not instantiated by GCC and Clang,
but it is instantiated by MSVC, so while the snippet is accepted by the former compilers,
More information about the cfe-commits
mailing list