clang 23.0.0git
EntityLinker.cpp
Go to the documentation of this file.
1//===- EntityLinker.cpp ----------------------------------------*- C++ -*-===//
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
16#include <cassert>
17
18using namespace clang::ssaf;
19
20//===----------------------------------------------------------------------===//
21// Error Message Constants
22//===----------------------------------------------------------------------===//
23
24namespace ErrorMessages {
25
26static constexpr const char *EntityLinkerFatalErrorPrefix =
27 "EntityLinker: Corrupted TUSummary or logic bug";
28
29static constexpr const char *EntityAlreadyExistsInLinkageTable =
30 "{0} - {1} with {2} already exists in LUSummary";
31
32static constexpr const char *MissingLinkageInformation =
33 "{0} - {1} missing linkage information in TUSummary";
34
35static constexpr const char *DuplicateEntityIdInTUSummary =
36 "{0} - Duplicate {1} in EntityResolutionTable";
37
38static constexpr const char *EntityNotFoundInResolutionTable =
39 "{0} - {1} not found in EntityResolutionTable";
40
41static constexpr const char *FailedToInsertEntityIntoOutputSummary =
42 "{0} - Failed to insert data for {1} with {2} against {3} to LUSummary";
43
44static constexpr const char *DuplicateTUNamespace =
45 "failed to link TU summary: duplicate {0}";
46
47} // namespace ErrorMessages
48
51 const NestedBuildNamespace &EntityNamespace,
53 switch (Linkage) {
56 return EntityNamespace.makeQualified(LUNamespace);
58 return NestedBuildNamespace(LUNamespace);
59 }
60
61 llvm_unreachable("Unhandled EntityLinkage::LinkageType variant");
62}
63
64EntityId EntityLinker::resolveEntity(const EntityName &OldName,
65 const EntityLinkage &Linkage) {
66 NestedBuildNamespace NewNamespace = resolveNamespace(
67 Output.LUNamespace, OldName.Namespace, Linkage.getLinkage());
68
69 EntityName NewName(OldName.USR, OldName.Suffix, NewNamespace);
70
71 // NewId construction will always return a fresh id for `None` and `Internal`
72 // linkage entities since their namespaces will be different even if their
73 // names clash. For `External` linkage entities with identical names this
74 // function will return the id assigned at the first insertion.
75 EntityId NewId = Output.IdTable.getId(NewName);
76
77 auto [_, Inserted] = Output.LinkageTable.try_emplace(NewId, Linkage);
78 if (!Inserted) {
79 // Insertion failure for `None` and `Internal` linkage is a fatal error
80 // because these entities have unique namespaces and should never collide.
81 // `External` linkage entities may collide.
82 if (Linkage.getLinkage() == EntityLinkage::LinkageType::None ||
86 Linkage);
87 }
88 }
89
90 return NewId;
91}
92
93std::map<EntityId, EntityId>
94EntityLinker::resolve(const TUSummaryEncoding &Summary) {
95 std::map<EntityId, EntityId> EntityResolutionTable;
96
97 Summary.IdTable.forEach([&](const EntityName &OldName, const EntityId OldId) {
98 auto Iter = Summary.LinkageTable.find(OldId);
99 if (Iter == Summary.LinkageTable.end()) {
102 }
103
104 const EntityLinkage &Linkage = Iter->second;
105
106 EntityId NewId = resolveEntity(OldName, Linkage);
107
108 auto [_, Inserted] = EntityResolutionTable.insert({OldId, NewId});
109 if (!Inserted) {
112 }
113 });
114
115 return EntityResolutionTable;
116}
117
118std::vector<EntitySummaryEncoding *>
119EntityLinker::merge(TUSummaryEncoding &Summary,
120 const std::map<EntityId, EntityId> &EntityResolutionTable) {
121 std::vector<EntitySummaryEncoding *> PatchTargets;
122
123 for (auto &[SN, DataMap] : Summary.Data) {
124 auto &OutputSummaryData = Output.Data[SN];
125
126 for (auto &[OldId, ES] : DataMap) {
127 auto Iter = EntityResolutionTable.find(OldId);
128 if (Iter == EntityResolutionTable.end()) {
131 }
132
133 const auto NewId = Iter->second;
134
135 auto [It, Inserted] = OutputSummaryData.try_emplace(NewId, std::move(ES));
136
137 if (Inserted) {
138 PatchTargets.push_back(It->second.get());
139 } else {
140 // Safe to retrieve linkage using .at since the resolve step ensures
141 // linkage information is always present for every OldId.
142 auto Linkage = Summary.LinkageTable.at(OldId);
143
144 // Insertion should never fail for `None` and `Internal` linkage
145 // entities because these entities will have different namespaces across
146 // TUs even if their names match.
147 if (Linkage.getLinkage() == EntityLinkage::LinkageType::None ||
152 }
153
154 // TODO: Insertion is expected to fail for duplicate occurrences of
155 // `External` linkage entities. Report these cases in a "debug" mode to
156 // help debug potential ODR violations.
157 }
158 }
159 }
160
161 return PatchTargets;
162}
163
164void EntityLinker::patch(
165 const std::vector<EntitySummaryEncoding *> &PatchTargets,
166 const std::map<EntityId, EntityId> &EntityResolutionTable) {
167 for (auto *PatchTarget : PatchTargets) {
168 assert(PatchTarget && "EntityLinker::patch: Patch target cannot be null");
169 PatchTarget->patch(EntityResolutionTable);
170 }
171}
172
173llvm::Error EntityLinker::link(std::unique_ptr<TUSummaryEncoding> Summary) {
174 auto [_, Inserted] = ProcessedTUNamespaces.insert(Summary->TUNamespace);
175 if (!Inserted) {
176 return ErrorBuilder::create(std::errc::invalid_argument,
178 Summary->TUNamespace)
179 .build();
180 }
181
182 TUSummaryEncoding &SummaryRef = *Summary;
183
184 auto EntityResolutionTable = resolve(SummaryRef);
185 auto PatchTargets = merge(SummaryRef, EntityResolutionTable);
186 patch(PatchTargets, EntityResolutionTable);
187
188 return llvm::Error::success();
189}
static NestedBuildNamespace resolveNamespace(const NestedBuildNamespace &LUNamespace, const NestedBuildNamespace &EntityNamespace, EntityLinkage::LinkageType Linkage)
void forEach(llvm::function_ref< void(const EntityName &, EntityId)> Callback) const
Invokes the callback for each entity in the table.
Lightweight opaque handle representing an entity in an EntityIdTable.
Definition EntityId.h:31
Represents the linkage properties of an entity in the program model.
@ None
local variables, function parameters
@ Internal
static functions/variables, anonymous namespace
@ External
globally visible across translation units
llvm::Error link(std::unique_ptr< TUSummaryEncoding > Summary)
Links a TU summary into a LU summary.
Uniquely identifies an entity in a program.
Definition EntityName.h:28
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
static void fatal(const char *Fmt, Args &&...ArgVals)
Report a fatal error with formatted message and terminate execution.
llvm::Error build() const
Build and return the final error.
Represents a hierarchical sequence of build namespaces.
NestedBuildNamespace makeQualified(NestedBuildNamespace Namespace) const
Creates a new NestedBuildNamespace by appending additional namespace.
Represents a translation unit summary in its serialized encoding.
static constexpr const char * EntityAlreadyExistsInLinkageTable
static constexpr const char * DuplicateTUNamespace
static constexpr const char * EntityLinkerFatalErrorPrefix
static constexpr const char * DuplicateEntityIdInTUSummary
static constexpr const char * MissingLinkageInformation
static constexpr const char * FailedToInsertEntityIntoOutputSummary
static constexpr const char * EntityNotFoundInResolutionTable
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
Definition Linkage.h:24