1//===--- Mangle.h - Mangle C++ Names ----------------------------*- 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//
9// Defines the C++ name mangling interface.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_MANGLE_H
14#define LLVM_CLANG_AST_MANGLE_H
15
16#include "clang/AST/Decl.h"
17#include "clang/AST/GlobalDecl.h"
18#include "clang/AST/Type.h"
19#include "clang/Basic/ABI.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/Support/Casting.h"
22#include <optional>
23
24namespace llvm {
25 class raw_ostream;
26}
27
28namespace clang {
29 class ASTContext;
30 class BlockDecl;
31 class CXXConstructorDecl;
32 class CXXDestructorDecl;
33 class CXXMethodDecl;
34 class FunctionDecl;
35 struct MethodVFTableLocation;
36 class NamedDecl;
37 class ObjCMethodDecl;
38 class StringLiteral;
39 struct ThisAdjustment;
40 struct ThunkInfo;
41 class VarDecl;
42
43/// MangleContext - Context for tracking state which persists across multiple
44/// calls to the C++ name mangler.
45class MangleContext {
46public:
47 enum ManglerKind {
48 MK_Itanium,
49 MK_Microsoft
50 };
51
52private:
53 virtual void anchor();
54
55 ASTContext &Context;
56 DiagnosticsEngine &Diags;
57 const ManglerKind Kind;
58 /// For aux target. If true, uses mangling number for aux target from
59 /// ASTContext.
60 bool IsAux = false;
61
62 llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
63 llvm::DenseMap<const BlockDecl*, unsigned> LocalBlockIds;
64 llvm::DenseMap<const NamedDecl*, uint64_t> AnonStructIds;
65 llvm::DenseMap<const FunctionDecl*, unsigned> FuncAnonStructSize;
66
67public:
68 ManglerKind getKind() const { return Kind; }
69
70 bool isAux() const { return IsAux; }
71
72 explicit MangleContext(ASTContext &Context, DiagnosticsEngine &Diags,
73 ManglerKind Kind, bool IsAux = false)
74 : Context(Context), Diags(Diags), Kind(Kind), IsAux(IsAux) {}
75
76 virtual ~MangleContext() { }
77
78 ASTContext &getASTContext() const { return Context; }
79
80 DiagnosticsEngine &getDiags() const { return Diags; }
81
82 virtual void startNewFunction() { LocalBlockIds.clear(); }
83
84 unsigned getBlockId(const BlockDecl *BD, bool Local) {
85 llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
86 = Local? LocalBlockIds : GlobalBlockIds;
87 std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::iterator, bool>
88 Result = BlockIds.insert(KV: std::make_pair(x&: BD, y: BlockIds.size()));
89 return Result.first->second;
90 }
91
92 uint64_t getAnonymousStructId(const NamedDecl *D,
93 const FunctionDecl *FD = nullptr) {
94 auto FindResult = AnonStructIds.find(Val: D);
95 if (FindResult != AnonStructIds.end())
96 return FindResult->second;
97
98 // If FunctionDecl is passed in, the anonymous structID will be per-function
99 // based.
100 unsigned Id = FD ? FuncAnonStructSize[FD]++ : AnonStructIds.size();
101 std::pair<llvm::DenseMap<const NamedDecl *, uint64_t>::iterator, bool>
102 Result = AnonStructIds.insert(KV: std::make_pair(x&: D, y&: Id));
103 return Result.first->second;
104 }
105
106 uint64_t getAnonymousStructIdForDebugInfo(const NamedDecl *D) {
107 llvm::DenseMap<const NamedDecl *, uint64_t>::iterator Result =
108 AnonStructIds.find(Val: D);
109 // The decl should already be inserted, but return 0 in case it is not.
110 if (Result == AnonStructIds.end())
111 return 0;
112 return Result->second;
113 }
114
115 virtual std::string getLambdaString(const CXXRecordDecl *Lambda) = 0;
116
117 /// @name Mangler Entry Points
118 /// @{
119
120 bool shouldMangleDeclName(const NamedDecl *D);
121 virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
122 virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
123
124 virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) {
125 return false;
126 }
127
128 virtual void needsUniqueInternalLinkageNames() { }
129
130 // FIXME: consider replacing raw_ostream & with something like SmallString &.
131 void mangleName(GlobalDecl GD, raw_ostream &);
132 virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0;
133 virtual void mangleThunk(const CXXMethodDecl *MD,
134 const ThunkInfo &Thunk,
135 raw_ostream &) = 0;
136 virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
137 const ThisAdjustment &ThisAdjustment,
138 raw_ostream &) = 0;
139 virtual void mangleReferenceTemporary(const VarDecl *D,
140 unsigned ManglingNumber,
141 raw_ostream &) = 0;
142 virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
143 virtual void mangleCXXRTTIName(QualType T, raw_ostream &,
144 bool NormalizeIntegers = false) = 0;
145 virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
146 virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
147
148 void mangleGlobalBlock(const BlockDecl *BD,
149 const NamedDecl *ID,
150 raw_ostream &Out);
151 void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT,
152 const BlockDecl *BD, raw_ostream &Out);
153 void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT,
154 const BlockDecl *BD, raw_ostream &Out);
155 void mangleBlock(const DeclContext *DC, const BlockDecl *BD,
156 raw_ostream &Out);
157
158 void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &OS,
159 bool includePrefixByte = true,
160 bool includeCategoryNamespace = true);
161 void mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD,
162 raw_ostream &);
163
164 virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0;
165
166 virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0;
167
168 virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
169 raw_ostream &) = 0;
170
171 virtual void mangleSEHFilterExpression(GlobalDecl EnclosingDecl,
172 raw_ostream &Out) = 0;
173
174 virtual void mangleSEHFinallyBlock(GlobalDecl EnclosingDecl,
175 raw_ostream &Out) = 0;
176
177 /// Generates a unique string for an externally visible type for use with TBAA
178 /// or type uniquing.
179 /// TODO: Extend this to internal types by generating names that are unique
180 /// across translation units so it can be used with LTO.
181 virtual void mangleCanonicalTypeName(QualType T, raw_ostream &,
182 bool NormalizeIntegers = false) = 0;
183
184 /// @}
185};
186
187class ItaniumMangleContext : public MangleContext {
188public:
189 using DiscriminatorOverrideTy =
190 std::optional<unsigned> (*)(ASTContext &, const NamedDecl *);
191 explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D,
192 bool IsAux = false)
193 : MangleContext(C, D, MK_Itanium, IsAux) {}
194
195 virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0;
196 virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0;
197 virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
198 const CXXRecordDecl *Type,
199 raw_ostream &) = 0;
200 virtual void mangleItaniumThreadLocalInit(const VarDecl *D,
201 raw_ostream &) = 0;
202 virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
203 raw_ostream &) = 0;
204
205 virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
206 raw_ostream &) = 0;
207 virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
208 raw_ostream &) = 0;
209
210 virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
211
212 virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
213
214 virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 0;
215
216 // This has to live here, otherwise the CXXNameMangler won't have access to
217 // it.
218 virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;
219 static bool classof(const MangleContext *C) {
220 return C->getKind() == MK_Itanium;
221 }
222
223 static ItaniumMangleContext *
224 create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false);
225 static ItaniumMangleContext *create(ASTContext &Context,
226 DiagnosticsEngine &Diags,
227 DiscriminatorOverrideTy Discriminator,
228 bool IsAux = false);
229};
230
231class MicrosoftMangleContext : public MangleContext {
232public:
233 explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D,
234 bool IsAux = false)
235 : MangleContext(C, D, MK_Microsoft, IsAux) {}
236
237 /// Mangle vftable symbols. Only a subset of the bases along the path
238 /// to the vftable are included in the name. It's up to the caller to pick
239 /// them correctly.
240 virtual void mangleCXXVFTable(const CXXRecordDecl *Derived,
241 ArrayRef<const CXXRecordDecl *> BasePath,
242 raw_ostream &Out) = 0;
243
244 /// Mangle vbtable symbols. Only a subset of the bases along the path
245 /// to the vbtable are included in the name. It's up to the caller to pick
246 /// them correctly.
247 virtual void mangleCXXVBTable(const CXXRecordDecl *Derived,
248 ArrayRef<const CXXRecordDecl *> BasePath,
249 raw_ostream &Out) = 0;
250
251 virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
252 unsigned GuardNum,
253 raw_ostream &Out) = 0;
254
255 virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
256 const MethodVFTableLocation &ML,
257 raw_ostream &Out) = 0;
258
259 virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD,
260 const CXXRecordDecl *DstRD,
261 raw_ostream &Out) = 0;
262
263 virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
264 bool IsUnaligned, uint32_t NumEntries,
265 raw_ostream &Out) = 0;
266
267 virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
268 raw_ostream &Out) = 0;
269
270 virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
271 CXXCtorType CT, uint32_t Size,
272 uint32_t NVOffset, int32_t VBPtrOffset,
273 uint32_t VBIndex, raw_ostream &Out) = 0;
274
275 virtual void mangleCXXRTTIBaseClassDescriptor(
276 const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
277 uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
278
279 virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
280 raw_ostream &Out) = 0;
281 virtual void
282 mangleCXXRTTIClassHierarchyDescriptor(const CXXRecordDecl *Derived,
283 raw_ostream &Out) = 0;
284
285 virtual void
286 mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
287 ArrayRef<const CXXRecordDecl *> BasePath,
288 raw_ostream &Out) = 0;
289
290 static bool classof(const MangleContext *C) {
291 return C->getKind() == MK_Microsoft;
292 }
293
294 static MicrosoftMangleContext *
295 create(ASTContext &Context, DiagnosticsEngine &Diags, bool IsAux = false);
296};
297
298class ASTNameGenerator {
299public:
300 explicit ASTNameGenerator(ASTContext &Ctx);
301 ~ASTNameGenerator();
302
303 /// Writes name for \p D to \p OS.
304 /// \returns true on failure, false on success.
305 bool writeName(const Decl *D, raw_ostream &OS);
306
307 /// \returns name for \p D
308 std::string getName(const Decl *D);
309
310 /// \returns all applicable mangled names.
311 /// For example C++ constructors/destructors can have multiple.
312 std::vector<std::string> getAllManglings(const Decl *D);
313
314private:
315 class Implementation;
316 std::unique_ptr<Implementation> Impl;
317};
318}
319
320#endif
321

source code of clang/include/clang/AST/Mangle.h