1*6d8e9665Sisuckatcs //===--- TemplateVirtualMemberFunctionCheck.cpp - clang-tidy --------------===//
2*6d8e9665Sisuckatcs //
3*6d8e9665Sisuckatcs // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*6d8e9665Sisuckatcs // See https://llvm.org/LICENSE.txt for license information.
5*6d8e9665Sisuckatcs // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*6d8e9665Sisuckatcs //
7*6d8e9665Sisuckatcs //===----------------------------------------------------------------------===//
8*6d8e9665Sisuckatcs 
9*6d8e9665Sisuckatcs #include "TemplateVirtualMemberFunctionCheck.h"
10*6d8e9665Sisuckatcs #include "clang/ASTMatchers/ASTMatchFinder.h"
11*6d8e9665Sisuckatcs 
12*6d8e9665Sisuckatcs using namespace clang::ast_matchers;
13*6d8e9665Sisuckatcs 
14*6d8e9665Sisuckatcs namespace clang::tidy::portability {
15*6d8e9665Sisuckatcs namespace {
16*6d8e9665Sisuckatcs AST_MATCHER(CXXMethodDecl, isUsed) { return Node.isUsed(); }
17*6d8e9665Sisuckatcs } // namespace
18*6d8e9665Sisuckatcs 
19*6d8e9665Sisuckatcs void TemplateVirtualMemberFunctionCheck::registerMatchers(MatchFinder *Finder) {
20*6d8e9665Sisuckatcs   Finder->addMatcher(
21*6d8e9665Sisuckatcs       cxxMethodDecl(ofClass(classTemplateSpecializationDecl(
22*6d8e9665Sisuckatcs                                 unless(isExplicitTemplateSpecialization()))
23*6d8e9665Sisuckatcs                                 .bind("specialization")),
24*6d8e9665Sisuckatcs                     isVirtual(), unless(isUsed()),
25*6d8e9665Sisuckatcs                     unless(cxxDestructorDecl(isDefaulted())))
26*6d8e9665Sisuckatcs           .bind("method"),
27*6d8e9665Sisuckatcs       this);
28*6d8e9665Sisuckatcs }
29*6d8e9665Sisuckatcs 
30*6d8e9665Sisuckatcs void TemplateVirtualMemberFunctionCheck::check(
31*6d8e9665Sisuckatcs     const MatchFinder::MatchResult &Result) {
32*6d8e9665Sisuckatcs   const auto *ImplicitSpecialization =
33*6d8e9665Sisuckatcs       Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
34*6d8e9665Sisuckatcs   const auto *MethodDecl = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
35*6d8e9665Sisuckatcs 
36*6d8e9665Sisuckatcs   diag(MethodDecl->getLocation(),
37*6d8e9665Sisuckatcs        "unspecified virtual member function instantiation; the virtual "
38*6d8e9665Sisuckatcs        "member function is not instantiated but it might be with a "
39*6d8e9665Sisuckatcs        "different compiler");
40*6d8e9665Sisuckatcs   diag(ImplicitSpecialization->getPointOfInstantiation(),
41*6d8e9665Sisuckatcs        "template instantiated here", DiagnosticIDs::Note);
42*6d8e9665Sisuckatcs }
43*6d8e9665Sisuckatcs 
44*6d8e9665Sisuckatcs } // namespace clang::tidy::portability
45