13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/Support/Error.h"
18#include "llvm/Support/raw_ostream.h"
28struct MethodFamilyUnionFind {
29 EntityId find(EntityId E);
30 void unionSets(EntityId A, EntityId B);
32 auto keys()
const {
return llvm::make_first_range(Roots); }
35 llvm::DenseMap<EntityId, EntityId> Roots;
38class VirtualMethodFamilyAnalysis final
40 VirtualMethodSummary> {
42 llvm::Error add(EntityId Id,
const VirtualMethodSummary &Summary)
override {
44 return llvm::Error::success();
47 llvm::Error finalize()
override;
51 void groupParamsAndReturnEntities();
54 void unionParamsAndReturnEntitiesInSummaries(
const VirtualMethodSummary &LHS,
55 const VirtualMethodSummary &RHS);
57 MethodFamilyUnionFind Family;
58 std::map<EntityId, const VirtualMethodSummary *> Data;
63 auto It = Roots.find(E);
64 if (It == Roots.end()) {
65 Roots.try_emplace(E, E);
70 EntityId Root = find(It->second);
71 Roots.insert_or_assign(E, Root);
75void MethodFamilyUnionFind::unionSets(EntityId A, EntityId B) {
76 EntityId RootA = find(A);
77 EntityId RootB = find(B);
83 std::swap(RootA, RootB);
85 Roots.insert_or_assign(RootB, RootA);
88void VirtualMethodFamilyAnalysis::unionParamsAndReturnEntitiesInSummaries(
89 const VirtualMethodSummary &LHS,
const VirtualMethodSummary &RHS) {
93 using llvm::zip_equal;
95 Family.unionSets(LParam, RParam);
101void VirtualMethodFamilyAnalysis::groupParamsAndReturnEntities() {
102 for (
const VirtualMethodSummary *CurrSum : llvm::make_second_range(Data)) {
103 for (EntityId OverriddenMethodId : CurrSum->OverriddenMethods) {
104 auto BaseSumIt = Data.find(OverriddenMethodId);
105 assert(BaseSumIt != Data.end());
106 const VirtualMethodSummary &BaseSum = *BaseSumIt->second;
107 unionParamsAndReturnEntitiesInSummaries(*CurrSum, BaseSum);
112llvm::Error VirtualMethodFamilyAnalysis::finalize() {
113 groupParamsAndReturnEntities();
115 auto &
R = getResult();
116 for (EntityId E : Family.keys())
117 R.RetAndParamData.insert({E, Family.find(E)});
118 return llvm::Error::success();
121static AnalysisRegistry::Add<VirtualMethodFamilyAnalysis>
131 llvm::interleaveComma(Ids, OS, [&](
EntityId Id) { OS << Id; });
135namespace clang::ssaf {
139 OS <<
"VirtualMethodSummary { params=";
146 OS <<
", overridden=";
153 OS <<
"VirtualMethodFamilyAnalysisResult with " << R.RetAndParamData.size()
155 if (R.RetAndParamData.empty())
159 using Entry = std::pair<EntityId, EntityId>;
161 R.RetAndParamData.end());
163 [](
const Entry &L,
const Entry &R) {
return L.first < R.first; });
166 for (
const auto &[Id, FamilyId] : Entries)
167 OS <<
" " << Id <<
" -> " << FamilyId <<
"\n";
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI)
static AnalysisRegistry::Add< VirtualMethodFamilyAnalysis > RegisterAnalysis("Override-family equivalence classes for virtual methods")
static void printEntityIds(llvm::raw_ostream &OS, llvm::ArrayRef< EntityId > Ids)
Lightweight opaque handle representing an entity in an EntityIdTable.
Typed intermediate that concrete summary analyses inherit from.
volatile int VirtualMethodFamilyAnalysisAnchorSource
std::vector< EntityId > ParamEntities
EntityIds of each ParmVarDecl, in source order.
std::optional< EntityId > ReturnEntity
EntityId of the synthetic return-slot entity for this method.
std::vector< EntityId > OverriddenMethods
The result of CXXMethodDecl::overridden_methods().