1//===- VirtualMethodEntityExtractor.cpp ----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Extract what virtual methods override what other methods.
10// The parameters might be also important for consumers so collect those as
11// well - alongside with the ID of the return value.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclCXX.h"
18#include "clang/AST/DynamicRecursiveASTVisitor.h"
19#include "clang/ScalableStaticAnalysis/Analyses/VirtualMethodFamily/VirtualMethodFamily.h"
20#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
21#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
22#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
23#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
24#include <memory>
25#include <optional>
26
27using namespace clang;
28using namespace ssaf;
29
30namespace {
31
32class VirtualMethodEntityExtractor final : public TUSummaryExtractor,
33 ConstDynamicRecursiveASTVisitor {
34public:
35 explicit VirtualMethodEntityExtractor(TUSummaryBuilder &Builder)
36 : TUSummaryExtractor(Builder) {
37 ShouldVisitTemplateInstantiations = true;
38 ShouldWalkTypesOfTypeLocs = false;
39 ShouldVisitImplicitCode = false;
40 ShouldVisitLambdaBody = true;
41 }
42
43private:
44 void HandleTranslationUnit(ASTContext &Ctx) override { TraverseAST(AST: Ctx); }
45
46 bool VisitCXXMethodDecl(const CXXMethodDecl *MD) override;
47};
48} // namespace
49
50bool VirtualMethodEntityExtractor::VisitCXXMethodDecl(const CXXMethodDecl *MD) {
51 if (!MD->isVirtual())
52 return true;
53
54 std::optional<EntityId> MethodId = addEntity(D: MD);
55 if (!MethodId)
56 return true;
57
58 auto Summary = std::make_unique<VirtualMethodSummary>();
59 Summary->ParamEntities.reserve(n: MD->getNumParams());
60
61 for (const ParmVarDecl *P : MD->parameters()) {
62 auto ParamId = addEntity(D: P);
63 if (!ParamId) {
64 // If we can't get an EntityId for a parameter, drop the entire summary
65 // rather than leaving a half-populated record.
66 return true;
67 }
68 Summary->ParamEntities.push_back(x: ParamId.value());
69 }
70
71 if (auto ReturnId = addEntityForReturn(FD: MD))
72 Summary->ReturnEntity = ReturnId.value();
73
74 for (const CXXMethodDecl *Overridden : MD->overridden_methods()) {
75 // We may not be able to convert methods that are coming from system
76 // headers, so skip them gracefully.
77 if (auto OverriddenId = addEntity(D: Overridden))
78 Summary->OverriddenMethods.push_back(x: *OverriddenId);
79 }
80
81 SummaryBuilder.addSummary(Entity: MethodId.value(), Data: std::move(Summary));
82 return true;
83}
84
85static TUSummaryExtractorRegistry::Add<VirtualMethodEntityExtractor>
86 RegisterExtractor(VirtualMethodSummary::Name,
87 "Extract information about virtual methods");
88
89namespace clang::ssaf {
90// NOLINTNEXTLINE(misc-use-internal-linkage)
91volatile int VirtualMethodEntityExtractorAnchorSource = 0;
92} // namespace clang::ssaf
93