blob: 83d9ed66788e39c33811ba098392560d2383ebb9 [file] [log] [blame]
Peter Collingbourne14110472011-01-13 18:57:25 +00001//===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===//
2//
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 generic name mangling support for blocks and Objective-C.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/AST/Mangle.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/Basic/ABI.h"
21#include "clang/Basic/SourceManager.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/raw_ostream.h"
24#include "llvm/Support/ErrorHandling.h"
25
26#define MANGLE_CHECKER 0
27
28#if MANGLE_CHECKER
29#include <cxxabi.h>
30#endif
31
32using namespace clang;
33
34// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
35// much to be desired. Come up with a better mangling scheme.
36
37namespace {
38
39static void mangleFunctionBlock(MangleContext &Context,
40 llvm::StringRef Outer,
41 const BlockDecl *BD,
42 llvm::SmallVectorImpl<char> &Res) {
43 llvm::raw_svector_ostream Out(Res);
44 Out << "__" << Outer << "_block_invoke_" << Context.getBlockId(BD, true);
45}
46
47static void checkMangleDC(const DeclContext *DC, const BlockDecl *BD) {
48#ifndef NDEBUG
49 const DeclContext *ExpectedDC = BD->getDeclContext();
50 while (isa<BlockDecl>(ExpectedDC) || isa<EnumDecl>(ExpectedDC))
51 ExpectedDC = ExpectedDC->getParent();
52 assert(DC == ExpectedDC && "Given decl context did not match expected!");
53#endif
54}
55
56}
57
58void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
59 llvm::SmallVectorImpl<char> &Res) {
60 llvm::raw_svector_ostream Out(Res);
61 Out << "__block_global_" << getBlockId(BD, false);
62}
63
64void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
65 CXXCtorType CT, const BlockDecl *BD,
66 llvm::SmallVectorImpl<char> &Res) {
67 checkMangleDC(CD, BD);
68 llvm::SmallString<64> Buffer;
69 mangleCXXCtor(CD, CT, Buffer);
70 mangleFunctionBlock(*this, Buffer, BD, Res);
71}
72
73void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
74 CXXDtorType DT, const BlockDecl *BD,
75 llvm::SmallVectorImpl<char> &Res) {
76 checkMangleDC(DD, BD);
77 llvm::SmallString<64> Buffer;
78 mangleCXXDtor(DD, DT, Buffer);
79 mangleFunctionBlock(*this, Buffer, BD, Res);
80}
81
82void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
83 llvm::SmallVectorImpl<char> &Res) {
84 assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
85 checkMangleDC(DC, BD);
86
87 llvm::SmallString<64> Buffer;
88 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
89 mangleObjCMethodName(Method, Buffer);
90 } else {
91 const NamedDecl *ND = cast<NamedDecl>(DC);
92 if (IdentifierInfo *II = ND->getIdentifier())
93 Buffer = II->getName();
94 else {
95 // FIXME: We were doing a mangleUnqualifiedName() before, but that's
96 // a private member of a class that will soon itself be private to the
97 // Itanium C++ ABI object. What should we do now? Right now, I'm just
98 // calling the mangleName() method on the MangleContext; is there a
99 // better way?
100 mangleName(ND, Buffer);
101 }
102 }
103
104 mangleFunctionBlock(*this, Buffer, BD, Res);
105}
106
107void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
108 llvm::SmallVectorImpl<char> &Res) {
109 llvm::SmallString<64> Name;
110 llvm::raw_svector_ostream OS(Name), Out(Res);
111
112 const ObjCContainerDecl *CD =
113 dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
114 assert (CD && "Missing container decl in GetNameForMethod");
115 OS << (MD->isInstanceMethod() ? '-' : '+') << '[' << CD->getName();
116 if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD))
117 OS << '(' << CID << ')';
118 OS << ' ' << MD->getSelector().getAsString() << ']';
119
120 Out << OS.str().size() << OS.str();
121}
122
123void MangleContext::mangleBlock(const BlockDecl *BD,
124 llvm::SmallVectorImpl<char> &Res) {
125 const DeclContext *DC = BD->getDeclContext();
126 while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC))
127 DC = DC->getParent();
128 if (DC->isFunctionOrMethod())
129 mangleBlock(DC, BD, Res);
130 else
131 mangleGlobalBlock(BD, Res);
132}