blob: e42b6fdb7917f6d476ff9ce55c517249ac82c38a [file] [log] [blame]
Douglas Gregor6ec36682009-02-18 23:53:56 +00001//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
Douglas Gregor5f2bfd42009-02-13 00:10:09 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implements C++ name mangling according to the Itanium C++ ABI,
11// which is used in GCC 3.2 and newer (and many compilers that are
12// ABI-compatible with GCC):
13//
14// http://www.codesourcery.com/public/cxx-abi/abi.html
15//
16//===----------------------------------------------------------------------===//
17#include "Mangle.h"
18#include "clang/AST/ASTContext.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
Anders Carlssona40c5e42009-03-07 22:03:21 +000021#include "clang/AST/DeclObjC.h"
Douglas Gregor6ec36682009-02-18 23:53:56 +000022#include "clang/Basic/SourceManager.h"
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000023#include "llvm/Support/Compiler.h"
24#include "llvm/Support/raw_ostream.h"
25using namespace clang;
26
27namespace {
28 class VISIBILITY_HIDDEN CXXNameMangler {
29 ASTContext &Context;
30 llvm::raw_ostream &Out;
31
Anders Carlsson3ac86b52009-04-15 05:36:58 +000032 const CXXConstructorDecl *Ctor;
33 CXXCtorType CtorType;
34
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000035 public:
36 CXXNameMangler(ASTContext &C, llvm::raw_ostream &os)
Anders Carlsson3ac86b52009-04-15 05:36:58 +000037 : Context(C), Out(os), Ctor(0), CtorType(Ctor_Complete) { }
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000038
39 bool mangle(const NamedDecl *D);
Anders Carlsson41aa8c12009-04-13 18:02:10 +000040 void mangleGuardVariable(const VarDecl *D);
Anders Carlsson3ac86b52009-04-15 05:36:58 +000041 void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
42
Anders Carlsson43f17402009-04-02 15:51:53 +000043 private:
44 bool mangleFunctionDecl(const FunctionDecl *FD);
45
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000046 void mangleFunctionEncoding(const FunctionDecl *FD);
47 void mangleName(const NamedDecl *ND);
48 void mangleUnqualifiedName(const NamedDecl *ND);
49 void mangleSourceName(const IdentifierInfo *II);
Anders Carlsson1b42c792009-04-02 16:24:45 +000050 void mangleLocalName(const NamedDecl *ND);
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000051 void mangleNestedName(const NamedDecl *ND);
52 void manglePrefix(const DeclContext *DC);
53 void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity);
54 void mangleCVQualifiers(unsigned Quals);
55 void mangleType(QualType T);
56 void mangleType(const BuiltinType *T);
57 void mangleType(const FunctionType *T);
58 void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType);
59 void mangleType(const TagType *T);
60 void mangleType(const ArrayType *T);
61 void mangleType(const MemberPointerType *T);
62 void mangleType(const TemplateTypeParmType *T);
Anders Carlssona40c5e42009-03-07 22:03:21 +000063 void mangleType(const ObjCInterfaceType *T);
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000064 void mangleExpression(Expr *E);
Anders Carlsson3ac86b52009-04-15 05:36:58 +000065 void mangleCXXCtorType(CXXCtorType T);
Douglas Gregor5f2bfd42009-02-13 00:10:09 +000066 };
67}
68
Anders Carlsson43f17402009-04-02 15:51:53 +000069static bool isInCLinkageSpecification(const Decl *D) {
70 for (const DeclContext *DC = D->getDeclContext();
71 !DC->isTranslationUnit(); DC = DC->getParent()) {
72 if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))
73 return Linkage->getLanguage() == LinkageSpecDecl::lang_c;
74 }
75
76 return false;
77}
78
79bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) {
80 // Clang's "overloadable" attribute extension to C/C++ implies
81 // name mangling (always).
Daniel Dunbarb11fa0d2009-04-13 21:08:27 +000082 if (FD->hasAttr<OverloadableAttr>()) {
Anders Carlsson43f17402009-04-02 15:51:53 +000083 ; // fall into mangling code unconditionally.
84 } else if (// C functions are not mangled
85 !Context.getLangOptions().CPlusPlus ||
86 // "main" is not mangled in C++
87 FD->isMain() ||
88 // No mangling in an "implicit extern C" header.
89 Context.getSourceManager().getFileCharacteristic(FD->getLocation())
90 == SrcMgr::C_ExternCSystem ||
91 // No name mangling in a C linkage specification.
92 isInCLinkageSpecification(FD))
93 return false;
94
95 // If we get here, mangle the decl name!
96 Out << "_Z";
97 mangleFunctionEncoding(FD);
98 return true;
99}
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000100
101bool CXXNameMangler::mangle(const NamedDecl *D) {
Chris Lattnerca3f25c2009-03-21 08:24:40 +0000102 // Any decl can be declared with __asm("foo") on it, and this takes
103 // precedence over all other naming in the .o file.
104 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
105 // If we have an asm name, then we use it as the mangling.
106 Out << '\01'; // LLVM IR Marker for __asm("foo")
107 Out << ALA->getLabel();
108 return true;
109 }
110
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000111 // <mangled-name> ::= _Z <encoding>
112 // ::= <data name>
113 // ::= <special-name>
114
115 // FIXME: Actually use a visitor to decode these?
Anders Carlsson43f17402009-04-02 15:51:53 +0000116 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
117 return mangleFunctionDecl(FD);
Chris Lattnerbc7a0292009-03-21 06:19:20 +0000118
Anders Carlsson329749c2009-04-02 16:05:20 +0000119 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
120 if (!Context.getLangOptions().CPlusPlus ||
Anders Carlsson9ccb0652009-04-11 01:19:45 +0000121 isInCLinkageSpecification(D) ||
122 D->getDeclContext()->isTranslationUnit())
Anders Carlsson329749c2009-04-02 16:05:20 +0000123 return false;
124
125 Out << "_Z";
126 mangleName(VD);
127 return true;
128 }
129
Anders Carlsson43f17402009-04-02 15:51:53 +0000130 return false;
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000131}
132
Anders Carlsson3ac86b52009-04-15 05:36:58 +0000133void CXXNameMangler::mangleCXXCtor(const CXXConstructorDecl *D,
134 CXXCtorType Type) {
135 assert(!Ctor && "Ctor already set!");
136 Ctor = D;
137 CtorType = Type;
138
139 mangle(D);
140}
141
Anders Carlsson41aa8c12009-04-13 18:02:10 +0000142void CXXNameMangler::mangleGuardVariable(const VarDecl *D)
143{
144 // <special-name> ::= GV <object name> # Guard variable for one-time
145 // # initialization
146
147 Out << "_ZGV";
148 mangleName(D);
149}
150
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000151void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {
152 // <encoding> ::= <function name> <bare-function-type>
153 mangleName(FD);
154 mangleBareFunctionType(FD->getType()->getAsFunctionType(), false);
155}
156
157static bool isStdNamespace(const DeclContext *DC) {
158 if (!DC->isNamespace() || !DC->getParent()->isTranslationUnit())
159 return false;
160
161 const NamespaceDecl *NS = cast<NamespaceDecl>(DC);
Douglas Gregor6ec36682009-02-18 23:53:56 +0000162 return NS->getOriginalNamespace()->getIdentifier()->isStr("std");
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000163}
164
165void CXXNameMangler::mangleName(const NamedDecl *ND) {
166 // <name> ::= <nested-name>
167 // ::= <unscoped-name>
168 // ::= <unscoped-template-name> <template-args>
169 // ::= <local-name> # See Scope Encoding below
170 //
171 // <unscoped-name> ::= <unqualified-name>
172 // ::= St <unqualified-name> # ::std::
173 if (ND->getDeclContext()->isTranslationUnit())
174 mangleUnqualifiedName(ND);
175 else if (isStdNamespace(ND->getDeclContext())) {
176 Out << "St";
177 mangleUnqualifiedName(ND);
Anders Carlsson1b42c792009-04-02 16:24:45 +0000178 } else if (isa<FunctionDecl>(ND->getDeclContext()))
179 mangleLocalName(ND);
180 else
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000181 mangleNestedName(ND);
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000182}
183
184void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) {
185 // <unqualified-name> ::= <operator-name>
186 // ::= <ctor-dtor-name>
187 // ::= <source-name>
188 DeclarationName Name = ND->getDeclName();
189 switch (Name.getNameKind()) {
190 case DeclarationName::Identifier:
191 mangleSourceName(Name.getAsIdentifierInfo());
192 break;
193
194 case DeclarationName::ObjCZeroArgSelector:
195 case DeclarationName::ObjCOneArgSelector:
196 case DeclarationName::ObjCMultiArgSelector:
197 assert(false && "Can't mangle Objective-C selector names here!");
198 break;
199
200 case DeclarationName::CXXConstructorName:
Anders Carlsson3ac86b52009-04-15 05:36:58 +0000201 if (ND == Ctor)
202 // If the named decl is the C++ constructor we're mangling, use the
203 // type we were given.
204 mangleCXXCtorType(CtorType);
205 else
206 // Otherwise, use the complete constructor name. This is relevant if a
207 // class with a constructor is declared within a constructor.
208 mangleCXXCtorType(Ctor_Complete);
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000209 break;
210
211 case DeclarationName::CXXDestructorName:
212 // <ctor-dtor-name> ::= D0 # deleting destructor
213 // ::= D1 # complete object destructor
214 // ::= D2 # base object destructor
215 //
216 // FIXME: We don't even have all of these destructors in the AST
217 // yet.
218 Out << "D0";
219 break;
220
221 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor219cc612009-02-13 01:28:03 +0000222 // <operator-name> ::= cv <type> # (cast)
223 Out << "cv";
224 mangleType(Context.getCanonicalType(Name.getCXXNameType()));
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000225 break;
226
227 case DeclarationName::CXXOperatorName:
228 mangleOperatorName(Name.getCXXOverloadedOperator(),
229 cast<FunctionDecl>(ND)->getNumParams());
230 break;
231
232 case DeclarationName::CXXUsingDirective:
233 assert(false && "Can't mangle a using directive name!");
Douglas Gregor219cc612009-02-13 01:28:03 +0000234 break;
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000235 }
236}
237
238void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) {
239 // <source-name> ::= <positive length number> <identifier>
240 // <number> ::= [n] <non-negative decimal integer>
241 // <identifier> ::= <unqualified source code identifier>
242 Out << II->getLength() << II->getName();
243}
244
245void CXXNameMangler::mangleNestedName(const NamedDecl *ND) {
246 // <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
247 // ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
248 // FIXME: no template support
249 Out << 'N';
250 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND))
251 mangleCVQualifiers(Method->getTypeQualifiers());
252 manglePrefix(ND->getDeclContext());
253 mangleUnqualifiedName(ND);
254 Out << 'E';
255}
256
Anders Carlsson1b42c792009-04-02 16:24:45 +0000257void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
258 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
259 // := Z <function encoding> E s [<discriminator>]
260 // <discriminator> := _ <non-negative number>
261 Out << 'Z';
262 mangleFunctionEncoding(cast<FunctionDecl>(ND->getDeclContext()));
263 Out << 'E';
264 mangleSourceName(ND->getIdentifier());
265}
266
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000267void CXXNameMangler::manglePrefix(const DeclContext *DC) {
268 // <prefix> ::= <prefix> <unqualified-name>
269 // ::= <template-prefix> <template-args>
270 // ::= <template-param>
271 // ::= # empty
272 // ::= <substitution>
273 // FIXME: We only handle mangling of namespaces and classes at the moment.
Anders Carlssonc8dee9c2009-04-01 00:42:16 +0000274 if (!DC->getParent()->isTranslationUnit())
275 manglePrefix(DC->getParent());
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000276
277 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(DC))
278 mangleSourceName(Namespace->getIdentifier());
279 else if (const RecordDecl *Record = dyn_cast<RecordDecl>(DC))
280 mangleSourceName(Record->getIdentifier());
281}
282
283void
284CXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity) {
285 switch (OO) {
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000286 // <operator-name> ::= nw # new
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000287 case OO_New: Out << "nw"; break;
288 // ::= na # new[]
289 case OO_Array_New: Out << "na"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000290 // ::= dl # delete
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000291 case OO_Delete: Out << "dl"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000292 // ::= da # delete[]
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000293 case OO_Array_Delete: Out << "da"; break;
294 // ::= ps # + (unary)
295 // ::= pl # +
296 case OO_Plus: Out << (Arity == 1? "ps" : "pl"); break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000297 // ::= ng # - (unary)
298 // ::= mi # -
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000299 case OO_Minus: Out << (Arity == 1? "ng" : "mi"); break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000300 // ::= ad # & (unary)
301 // ::= an # &
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000302 case OO_Amp: Out << (Arity == 1? "ad" : "an"); break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000303 // ::= de # * (unary)
304 // ::= ml # *
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000305 case OO_Star: Out << (Arity == 1? "de" : "ml"); break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000306 // ::= co # ~
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000307 case OO_Tilde: Out << "co"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000308 // ::= dv # /
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000309 case OO_Slash: Out << "dv"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000310 // ::= rm # %
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000311 case OO_Percent: Out << "rm"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000312 // ::= or # |
313 case OO_Pipe: Out << "or"; break;
314 // ::= eo # ^
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000315 case OO_Caret: Out << "eo"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000316 // ::= aS # =
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000317 case OO_Equal: Out << "aS"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000318 // ::= pL # +=
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000319 case OO_PlusEqual: Out << "pL"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000320 // ::= mI # -=
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000321 case OO_MinusEqual: Out << "mI"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000322 // ::= mL # *=
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000323 case OO_StarEqual: Out << "mL"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000324 // ::= dV # /=
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000325 case OO_SlashEqual: Out << "dV"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000326 // ::= rM # %=
327 case OO_PercentEqual: Out << "rM"; break;
328 // ::= aN # &=
329 case OO_AmpEqual: Out << "aN"; break;
330 // ::= oR # |=
331 case OO_PipeEqual: Out << "oR"; break;
332 // ::= eO # ^=
333 case OO_CaretEqual: Out << "eO"; break;
334 // ::= ls # <<
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000335 case OO_LessLess: Out << "ls"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000336 // ::= rs # >>
337 case OO_GreaterGreater: Out << "rs"; break;
338 // ::= lS # <<=
339 case OO_LessLessEqual: Out << "lS"; break;
340 // ::= rS # >>=
341 case OO_GreaterGreaterEqual: Out << "rS"; break;
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000342 // ::= eq # ==
343 case OO_EqualEqual: Out << "eq"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000344 // ::= ne # !=
345 case OO_ExclaimEqual: Out << "ne"; break;
346 // ::= lt # <
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000347 case OO_Less: Out << "lt"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000348 // ::= gt # >
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000349 case OO_Greater: Out << "gt"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000350 // ::= le # <=
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000351 case OO_LessEqual: Out << "le"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000352 // ::= ge # >=
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000353 case OO_GreaterEqual: Out << "ge"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000354 // ::= nt # !
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000355 case OO_Exclaim: Out << "nt"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000356 // ::= aa # &&
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000357 case OO_AmpAmp: Out << "aa"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000358 // ::= oo # ||
359 case OO_PipePipe: Out << "oo"; break;
360 // ::= pp # ++
361 case OO_PlusPlus: Out << "pp"; break;
362 // ::= mm # --
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000363 case OO_MinusMinus: Out << "mm"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000364 // ::= cm # ,
365 case OO_Comma: Out << "cm"; break;
366 // ::= pm # ->*
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000367 case OO_ArrowStar: Out << "pm"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000368 // ::= pt # ->
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000369 case OO_Arrow: Out << "pt"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000370 // ::= cl # ()
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000371 case OO_Call: Out << "cl"; break;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000372 // ::= ix # []
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000373 case OO_Subscript: Out << "ix"; break;
374 // UNSUPPORTED: ::= qu # ?
375
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000376 case OO_None:
377 case OO_Conditional:
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000378 case NUM_OVERLOADED_OPERATORS:
Douglas Gregor6ec36682009-02-18 23:53:56 +0000379 assert(false && "Not an overloaded operator");
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000380 break;
381 }
382}
383
384void CXXNameMangler::mangleCVQualifiers(unsigned Quals) {
385 // <CV-qualifiers> ::= [r] [V] [K] # restrict (C99), volatile, const
386 if (Quals & QualType::Restrict)
387 Out << 'r';
388 if (Quals & QualType::Volatile)
389 Out << 'V';
390 if (Quals & QualType::Const)
391 Out << 'K';
392}
393
394void CXXNameMangler::mangleType(QualType T) {
Anders Carlsson4843e582009-03-10 17:07:44 +0000395 // Only operate on the canonical type!
396 T = Context.getCanonicalType(T);
397
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000398 // FIXME: Should we have a TypeNodes.def to make this easier? (YES!)
399
400 // <type> ::= <CV-qualifiers> <type>
401 mangleCVQualifiers(T.getCVRQualifiers());
402
403 // ::= <builtin-type>
Anders Carlsson4843e582009-03-10 17:07:44 +0000404 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000405 mangleType(BT);
406 // ::= <function-type>
407 else if (const FunctionType *FT = dyn_cast<FunctionType>(T.getTypePtr()))
408 mangleType(FT);
409 // ::= <class-enum-type>
410 else if (const TagType *TT = dyn_cast<TagType>(T.getTypePtr()))
411 mangleType(TT);
412 // ::= <array-type>
413 else if (const ArrayType *AT = dyn_cast<ArrayType>(T.getTypePtr()))
414 mangleType(AT);
415 // ::= <pointer-to-member-type>
416 else if (const MemberPointerType *MPT
417 = dyn_cast<MemberPointerType>(T.getTypePtr()))
418 mangleType(MPT);
419 // ::= <template-param>
420 else if (const TemplateTypeParmType *TypeParm
421 = dyn_cast<TemplateTypeParmType>(T.getTypePtr()))
422 mangleType(TypeParm);
423 // FIXME: ::= <template-template-param> <template-args>
424 // FIXME: ::= <substitution> # See Compression below
425 // ::= P <type> # pointer-to
426 else if (const PointerType *PT = dyn_cast<PointerType>(T.getTypePtr())) {
427 Out << 'P';
428 mangleType(PT->getPointeeType());
429 }
430 // ::= R <type> # reference-to
Sebastian Redl7c80bd62009-03-16 23:22:08 +0000431 else if (const LValueReferenceType *RT =
432 dyn_cast<LValueReferenceType>(T.getTypePtr())) {
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000433 Out << 'R';
434 mangleType(RT->getPointeeType());
435 }
Sebastian Redl7c80bd62009-03-16 23:22:08 +0000436 // ::= O <type> # rvalue reference-to (C++0x)
437 else if (const RValueReferenceType *RT =
438 dyn_cast<RValueReferenceType>(T.getTypePtr())) {
439 Out << 'O';
440 mangleType(RT->getPointeeType());
441 }
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000442 // ::= C <type> # complex pair (C 2000)
443 else if (const ComplexType *CT = dyn_cast<ComplexType>(T.getTypePtr())) {
444 Out << 'C';
445 mangleType(CT->getElementType());
446 } else if (const VectorType *VT = dyn_cast<VectorType>(T.getTypePtr())) {
447 // GNU extension: vector types
448 Out << "U8__vector";
449 mangleType(VT->getElementType());
Anders Carlssona40c5e42009-03-07 22:03:21 +0000450 } else if (const ObjCInterfaceType *IT =
451 dyn_cast<ObjCInterfaceType>(T.getTypePtr())) {
452 mangleType(IT);
Anders Carlsson4843e582009-03-10 17:07:44 +0000453 }
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000454 // FIXME: ::= G <type> # imaginary (C 2000)
455 // FIXME: ::= U <source-name> <type> # vendor extended type qualifier
456 else
457 assert(false && "Cannot mangle unknown type");
458}
459
460void CXXNameMangler::mangleType(const BuiltinType *T) {
461 // <builtin-type> ::= v # void
462 // ::= w # wchar_t
463 // ::= b # bool
464 // ::= c # char
465 // ::= a # signed char
466 // ::= h # unsigned char
467 // ::= s # short
468 // ::= t # unsigned short
469 // ::= i # int
470 // ::= j # unsigned int
471 // ::= l # long
472 // ::= m # unsigned long
473 // ::= x # long long, __int64
474 // ::= y # unsigned long long, __int64
475 // ::= n # __int128
476 // UNSUPPORTED: ::= o # unsigned __int128
477 // ::= f # float
478 // ::= d # double
479 // ::= e # long double, __float80
480 // UNSUPPORTED: ::= g # __float128
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000481 // UNSUPPORTED: ::= Dd # IEEE 754r decimal floating point (64 bits)
482 // UNSUPPORTED: ::= De # IEEE 754r decimal floating point (128 bits)
483 // UNSUPPORTED: ::= Df # IEEE 754r decimal floating point (32 bits)
484 // UNSUPPORTED: ::= Dh # IEEE 754r half-precision floating point (16 bits)
485 // UNSUPPORTED: ::= Di # char32_t
486 // UNSUPPORTED: ::= Ds # char16_t
487 // ::= u <source-name> # vendor extended type
488 switch (T->getKind()) {
489 case BuiltinType::Void: Out << 'v'; break;
490 case BuiltinType::Bool: Out << 'b'; break;
491 case BuiltinType::Char_U: case BuiltinType::Char_S: Out << 'c'; break;
492 case BuiltinType::UChar: Out << 'h'; break;
493 case BuiltinType::UShort: Out << 't'; break;
494 case BuiltinType::UInt: Out << 'j'; break;
495 case BuiltinType::ULong: Out << 'm'; break;
496 case BuiltinType::ULongLong: Out << 'y'; break;
497 case BuiltinType::SChar: Out << 'a'; break;
498 case BuiltinType::WChar: Out << 'w'; break;
499 case BuiltinType::Short: Out << 's'; break;
500 case BuiltinType::Int: Out << 'i'; break;
501 case BuiltinType::Long: Out << 'l'; break;
502 case BuiltinType::LongLong: Out << 'x'; break;
503 case BuiltinType::Float: Out << 'f'; break;
504 case BuiltinType::Double: Out << 'd'; break;
505 case BuiltinType::LongDouble: Out << 'e'; break;
506
507 case BuiltinType::Overload:
508 case BuiltinType::Dependent:
509 assert(false &&
510 "Overloaded and dependent types shouldn't get to name mangling");
511 break;
512 }
513}
514
515void CXXNameMangler::mangleType(const FunctionType *T) {
516 // <function-type> ::= F [Y] <bare-function-type> E
517 Out << 'F';
518 // FIXME: We don't have enough information in the AST to produce the
519 // 'Y' encoding for extern "C" function types.
520 mangleBareFunctionType(T, /*MangleReturnType=*/true);
521 Out << 'E';
522}
523
524void CXXNameMangler::mangleBareFunctionType(const FunctionType *T,
525 bool MangleReturnType) {
526 // <bare-function-type> ::= <signature type>+
527 if (MangleReturnType)
528 mangleType(T->getResultType());
529
Douglas Gregor72564e72009-02-26 23:50:07 +0000530 const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(T);
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000531 assert(Proto && "Can't mangle K&R function prototypes");
532
Anders Carlssonc6c91bc2009-04-01 00:15:23 +0000533 if (Proto->getNumArgs() == 0) {
534 Out << 'v';
535 return;
536 }
537
Douglas Gregor72564e72009-02-26 23:50:07 +0000538 for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(),
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000539 ArgEnd = Proto->arg_type_end();
540 Arg != ArgEnd; ++Arg)
541 mangleType(*Arg);
Douglas Gregor219cc612009-02-13 01:28:03 +0000542
543 // <builtin-type> ::= z # ellipsis
544 if (Proto->isVariadic())
545 Out << 'z';
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000546}
547
548void CXXNameMangler::mangleType(const TagType *T) {
549 // <class-enum-type> ::= <name>
Anders Carlsson4843e582009-03-10 17:07:44 +0000550
551 if (!T->getDecl()->getIdentifier())
552 mangleName(T->getDecl()->getTypedefForAnonDecl());
553 else
554 mangleName(T->getDecl());
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000555}
556
557void CXXNameMangler::mangleType(const ArrayType *T) {
558 // <array-type> ::= A <positive dimension number> _ <element type>
559 // ::= A [<dimension expression>] _ <element type>
560 Out << 'A';
561 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T))
562 Out << CAT->getSize();
563 else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T))
564 mangleExpression(VAT->getSizeExpr());
565 else if (const DependentSizedArrayType *DSAT
566 = dyn_cast<DependentSizedArrayType>(T))
567 mangleExpression(DSAT->getSizeExpr());
568
569 Out << '_';
570 mangleType(T->getElementType());
571}
572
573void CXXNameMangler::mangleType(const MemberPointerType *T) {
574 // <pointer-to-member-type> ::= M <class type> <member type>
575 Out << 'M';
576 mangleType(QualType(T->getClass(), 0));
577 mangleType(T->getPointeeType());
578}
579
580void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
581 // <template-param> ::= T_ # first template parameter
582 // ::= T <parameter-2 non-negative number> _
583 if (T->getIndex() == 0)
584 Out << "T_";
585 else
586 Out << 'T' << (T->getIndex() - 1) << '_';
587}
588
Anders Carlssona40c5e42009-03-07 22:03:21 +0000589void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
590 mangleSourceName(T->getDecl()->getIdentifier());
591}
592
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000593void CXXNameMangler::mangleExpression(Expr *E) {
594 assert(false && "Cannot mangle expressions yet");
595}
596
Anders Carlsson3ac86b52009-04-15 05:36:58 +0000597void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
598 // <ctor-dtor-name> ::= C1 # complete object constructor
599 // ::= C2 # base object constructor
600 // ::= C3 # complete object allocating constructor
601 //
602 switch (T) {
603 case Ctor_Complete:
604 Out << "C1";
605 break;
606 case Ctor_Base:
607 Out << "C2";
608 break;
609 case Ctor_CompleteAllocating:
610 Out << "C3";
611 break;
612 }
613}
614
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000615namespace clang {
616 /// \brief Mangles the name of the declaration D and emits that name
617 /// to the given output stream.
618 ///
619 /// If the declaration D requires a mangled name, this routine will
620 /// emit that mangled name to \p os and return true. Otherwise, \p
621 /// os will be unchanged and this routine will return false. In this
622 /// case, the caller should just emit the identifier of the declaration
623 /// (\c D->getIdentifier()) as its name.
624 bool mangleName(const NamedDecl *D, ASTContext &Context,
625 llvm::raw_ostream &os) {
626 CXXNameMangler Mangler(Context, os);
Douglas Gregor6ec36682009-02-18 23:53:56 +0000627 if (!Mangler.mangle(D))
628 return false;
629
630 os.flush();
631 return true;
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000632 }
Anders Carlsson41aa8c12009-04-13 18:02:10 +0000633
Anders Carlsson3ac86b52009-04-15 05:36:58 +0000634 /// mangleGuardVariable - Returns the mangled name for a guard variable
635 /// for the passed in VarDecl.
Anders Carlsson41aa8c12009-04-13 18:02:10 +0000636 void mangleGuardVariable(const VarDecl *D, ASTContext &Context,
637 llvm::raw_ostream &os) {
638 CXXNameMangler Mangler(Context, os);
639 Mangler.mangleGuardVariable(D);
640
641 os.flush();
642 }
Anders Carlsson3ac86b52009-04-15 05:36:58 +0000643
644 void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
645 ASTContext &Context, llvm::raw_ostream &os) {
646 CXXNameMangler Mangler(Context, os);
647 Mangler.mangleCXXCtor(D, Type);
648
649 os.flush();
650 }
Douglas Gregor5f2bfd42009-02-13 00:10:09 +0000651}
652