Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/AST/Mangle.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- Mangle.cpp - 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
// Implements generic name mangling support for blocks and Objective-C.
10
//
11
//===----------------------------------------------------------------------===//
12
#include "clang/AST/Attr.h"
13
#include "clang/AST/ASTContext.h"
14
#include "clang/AST/Decl.h"
15
#include "clang/AST/DeclCXX.h"
16
#include "clang/AST/DeclObjC.h"
17
#include "clang/AST/DeclTemplate.h"
18
#include "clang/AST/ExprCXX.h"
19
#include "clang/AST/Mangle.h"
20
#include "clang/AST/VTableBuilder.h"
21
#include "clang/Basic/ABI.h"
22
#include "clang/Basic/SourceManager.h"
23
#include "clang/Basic/TargetInfo.h"
24
#include "llvm/ADT/StringExtras.h"
25
#include "llvm/IR/DataLayout.h"
26
#include "llvm/IR/Mangler.h"
27
#include "llvm/Support/ErrorHandling.h"
28
#include "llvm/Support/raw_ostream.h"
29
30
using namespace clang;
31
32
// FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
33
// much to be desired. Come up with a better mangling scheme.
34
35
static void mangleFunctionBlock(MangleContext &Context,
36
                                StringRef Outer,
37
                                const BlockDecl *BD,
38
1.11k
                                raw_ostream &Out) {
39
1.11k
  unsigned discriminator = Context.getBlockId(BD, true);
40
1.11k
  if (discriminator == 0)
41
895
    Out << "__" << Outer << "_block_invoke";
42
221
  else
43
221
    Out << "__" << Outer << "_block_invoke_" << discriminator+1;
44
1.11k
}
45
46
0
void MangleContext::anchor() { }
47
48
enum CCMangling {
49
  CCM_Other,
50
  CCM_Fast,
51
  CCM_RegCall,
52
  CCM_Vector,
53
  CCM_Std
54
};
55
56
51.1k
static bool isExternC(const NamedDecl *ND) {
57
51.1k
  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND))
58
46.0k
    return FD->isExternC();
59
5.04k
  return cast<VarDecl>(ND)->isExternC();
60
5.04k
}
61
62
static CCMangling getCallingConvMangling(const ASTContext &Context,
63
4.70M
                                         const NamedDecl *ND) {
64
4.70M
  const TargetInfo &TI = Context.getTargetInfo();
65
4.70M
  const llvm::Triple &Triple = TI.getTriple();
66
4.70M
  if (!Triple.isOSWindows() ||
67
4.70M
      
!(95.0k
Triple.getArch() == llvm::Triple::x8695.0k
||
68
95.0k
        
Triple.getArch() == llvm::Triple::x86_6444.6k
))
69
4.60M
    return CCM_Other;
70
93.4k
71
93.4k
  if (Context.getLangOpts().CPlusPlus && 
!isExternC(ND)51.1k
&&
72
93.4k
      
TI.getCXXABI() == TargetCXXABI::Microsoft50.9k
)
73
42.1k
    return CCM_Other;
74
51.3k
75
51.3k
  const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
76
51.3k
  if (!FD)
77
947
    return CCM_Other;
78
50.4k
  QualType T = FD->getType();
79
50.4k
80
50.4k
  const FunctionType *FT = T->castAs<FunctionType>();
81
50.4k
82
50.4k
  CallingConv CC = FT->getCallConv();
83
50.4k
  switch (CC) {
84
50.4k
  default:
85
50.1k
    return CCM_Other;
86
50.4k
  case CC_X86FastCall:
87
85
    return CCM_Fast;
88
50.4k
  case CC_X86StdCall:
89
49
    return CCM_Std;
90
50.4k
  case CC_X86VectorCall:
91
185
    return CCM_Vector;
92
50.4k
  }
93
50.4k
}
94
95
3.62M
bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
96
3.62M
  const ASTContext &ASTContext = getASTContext();
97
3.62M
98
3.62M
  CCMangling CC = getCallingConvMangling(ASTContext, D);
99
3.62M
  if (CC != CCM_Other)
100
174
    return true;
101
3.62M
102
3.62M
  // If the declaration has an owning module for linkage purposes that needs to
103
3.62M
  // be mangled, we must mangle its name.
104
3.62M
  if (!D->hasExternalFormalLinkage() && 
D->getOwningModuleForLinkage()1.22M
)
105
54
    return true;
106
3.62M
107
3.62M
  // In C, functions with no attributes never need to be mangled. Fastpath them.
108
3.62M
  if (!getASTContext().getLangOpts().CPlusPlus && 
!D->hasAttrs()1.13M
)
109
150k
    return false;
110
3.47M
111
3.47M
  // Any decl can be declared with __asm("foo") on it, and this takes precedence
112
3.47M
  // over all other naming in the .o file.
113
3.47M
  if (D->hasAttr<AsmLabelAttr>())
114
1.90k
    return true;
115
3.47M
116
3.47M
  return shouldMangleCXXName(D);
117
3.47M
}
118
119
1.08M
void MangleContext::mangleName(const NamedDecl *D, raw_ostream &Out) {
120
1.08M
  // Any decl can be declared with __asm("foo") on it, and this takes precedence
121
1.08M
  // over all other naming in the .o file.
122
1.08M
  if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) {
123
1.90k
    // If we have an asm name, then we use it as the mangling.
124
1.90k
125
1.90k
    // Adding the prefix can cause problems when one file has a "foo" and
126
1.90k
    // another has a "\01foo". That is known to happen on ELF with the
127
1.90k
    // tricks normally used for producing aliases (PR9177). Fortunately the
128
1.90k
    // llvm mangler on ELF is a nop, so we can just avoid adding the \01
129
1.90k
    // marker.  We also avoid adding the marker if this is an alias for an
130
1.90k
    // LLVM intrinsic.
131
1.90k
    char GlobalPrefix =
132
1.90k
        getASTContext().getTargetInfo().getDataLayout().getGlobalPrefix();
133
1.90k
    if (GlobalPrefix && 
!ALA->getLabel().startswith("llvm.")1.87k
)
134
1.87k
      Out << '\01'; // LLVM IR Marker for __asm("foo")
135
1.90k
136
1.90k
    Out << ALA->getLabel();
137
1.90k
    return;
138
1.90k
  }
139
1.07M
140
1.07M
  const ASTContext &ASTContext = getASTContext();
141
1.07M
  CCMangling CC = getCallingConvMangling(ASTContext, D);
142
1.07M
  bool MCXX = shouldMangleCXXName(D);
143
1.07M
  const TargetInfo &TI = Context.getTargetInfo();
144
1.07M
  if (CC == CCM_Other || 
(145
MCXX145
&&
TI.getCXXABI() == TargetCXXABI::Microsoft25
)) {
145
1.07M
    if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
146
0
      mangleObjCMethodName(OMD, Out);
147
1.07M
    else
148
1.07M
      mangleCXXName(D, Out);
149
1.07M
    return;
150
1.07M
  }
151
144
152
144
  Out << '\01';
153
144
  if (CC == CCM_Std)
154
18
    Out << '_';
155
126
  else if (CC == CCM_Fast)
156
37
    Out << '@';
157
89
  else if (CC == CCM_RegCall)
158
0
    Out << "__regcall3__";
159
144
160
144
  if (!MCXX)
161
120
    Out << D->getIdentifier()->getName();
162
24
  else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
163
0
    mangleObjCMethodName(OMD, Out);
164
24
  else
165
24
    mangleCXXName(D, Out);
166
144
167
144
  const FunctionDecl *FD = cast<FunctionDecl>(D);
168
144
  const FunctionType *FT = FD->getType()->castAs<FunctionType>();
169
144
  const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT);
170
144
  if (CC == CCM_Vector)
171
89
    Out << '@';
172
144
  Out << '@';
173
144
  if (!Proto) {
174
5
    Out << '0';
175
5
    return;
176
5
  }
177
139
  assert(!Proto->isVariadic());
178
139
  unsigned ArgWords = 0;
179
139
  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
180
2
    if (!MD->isStatic())
181
1
      ++ArgWords;
182
139
  for (const auto &AT : Proto->param_types())
183
235
    // Size should be aligned to pointer size.
184
235
    ArgWords +=
185
235
        llvm::alignTo(ASTContext.getTypeSize(AT), TI.getPointerWidth(0)) /
186
235
        TI.getPointerWidth(0);
187
139
  Out << ((TI.getPointerWidth(0) / 8) * ArgWords);
188
139
}
189
190
void MangleContext::mangleGlobalBlock(const BlockDecl *BD,
191
                                      const NamedDecl *ID,
192
92
                                      raw_ostream &Out) {
193
92
  unsigned discriminator = getBlockId(BD, false);
194
92
  if (ID) {
195
70
    if (shouldMangleDeclName(ID))
196
12
      mangleName(ID, Out);
197
58
    else {
198
58
      Out << ID->getIdentifier()->getName();
199
58
    }
200
70
  }
201
92
  if (discriminator == 0)
202
60
    Out << "_block_invoke";
203
32
  else
204
32
    Out << "_block_invoke_" << discriminator+1;
205
92
}
206
207
void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD,
208
                                    CXXCtorType CT, const BlockDecl *BD,
209
29
                                    raw_ostream &ResStream) {
210
29
  SmallString<64> Buffer;
211
29
  llvm::raw_svector_ostream Out(Buffer);
212
29
  mangleCXXCtor(CD, CT, Out);
213
29
  mangleFunctionBlock(*this, Buffer, BD, ResStream);
214
29
}
215
216
void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD,
217
                                    CXXDtorType DT, const BlockDecl *BD,
218
10
                                    raw_ostream &ResStream) {
219
10
  SmallString<64> Buffer;
220
10
  llvm::raw_svector_ostream Out(Buffer);
221
10
  mangleCXXDtor(DD, DT, Out);
222
10
  mangleFunctionBlock(*this, Buffer, BD, ResStream);
223
10
}
224
225
void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
226
1.07k
                                raw_ostream &Out) {
227
1.07k
  assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC));
228
1.07k
229
1.07k
  SmallString<64> Buffer;
230
1.07k
  llvm::raw_svector_ostream Stream(Buffer);
231
1.07k
  if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
232
31
    mangleObjCMethodName(Method, Stream);
233
1.04k
  } else {
234
1.04k
    assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
235
1.04k
           "expected a NamedDecl or BlockDecl");
236
1.04k
    if (isa<BlockDecl>(DC))
237
0
      for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
238
0
        (void) getBlockId(cast<BlockDecl>(DC), true);
239
1.04k
    assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
240
1.04k
           "expected a TranslationUnitDecl or a NamedDecl");
241
1.04k
    if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
242
0
      mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out);
243
1.04k
    else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC))
244
0
      mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out);
245
1.04k
    else if (auto ND = dyn_cast<NamedDecl>(DC)) {
246
1.04k
      if (!shouldMangleDeclName(ND) && 
ND->getIdentifier()846
)
247
846
        Stream << ND->getIdentifier()->getName();
248
200
      else {
249
200
        // FIXME: We were doing a mangleUnqualifiedName() before, but that's
250
200
        // a private member of a class that will soon itself be private to the
251
200
        // Itanium C++ ABI object. What should we do now? Right now, I'm just
252
200
        // calling the mangleName() method on the MangleContext; is there a
253
200
        // better way?
254
200
        mangleName(ND, Stream);
255
200
      }
256
1.04k
    }
257
1.04k
  }
258
1.07k
  mangleFunctionBlock(*this, Buffer, BD, Out);
259
1.07k
}
260
261
void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD,
262
234
                                                    raw_ostream &OS) {
263
234
  const ObjCContainerDecl *CD =
264
234
  dyn_cast<ObjCContainerDecl>(MD->getDeclContext());
265
234
  assert (CD && "Missing container decl in GetNameForMethod");
266
234
  OS << (MD->isInstanceMethod() ? 
'-'202
:
'+'32
) << '[';
267
234
  if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(CD)) {
268
3
    OS << CID->getClassInterface()->getName();
269
3
    OS << '(' << *CID << ')';
270
231
  } else {
271
231
    OS << CD->getName();
272
231
  }
273
234
  OS << ' ';
274
234
  MD->getSelector().print(OS);
275
234
  OS << ']';
276
234
}
277
278
void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
279
54
                                         raw_ostream &Out) {
280
54
  SmallString<64> Name;
281
54
  llvm::raw_svector_ostream OS(Name);
282
54
283
54
  mangleObjCMethodNameWithoutSize(MD, OS);
284
54
  Out << OS.str().size() << OS.str();
285
54
}
286
287
class ASTNameGenerator::Implementation {
288
  std::unique_ptr<MangleContext> MC;
289
  llvm::DataLayout DL;
290
291
public:
292
  explicit Implementation(ASTContext &Ctx)
293
227
      : MC(Ctx.createMangleContext()), DL(Ctx.getTargetInfo().getDataLayout()) {
294
227
  }
295
296
1.45k
  bool writeName(const Decl *D, raw_ostream &OS) {
297
1.45k
    // First apply frontend mangling.
298
1.45k
    SmallString<128> FrontendBuf;
299
1.45k
    llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
300
1.45k
    if (auto *FD = dyn_cast<FunctionDecl>(D)) {
301
278
      if (FD->isDependentContext())
302
64
        return true;
303
214
      if (writeFuncOrVarName(FD, FrontendBufOS))
304
0
        return true;
305
1.17k
    } else if (auto *VD = dyn_cast<VarDecl>(D)) {
306
125
      if (writeFuncOrVarName(VD, FrontendBufOS))
307
0
        return true;
308
1.04k
    } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
309
180
      MC->mangleObjCMethodNameWithoutSize(MD, OS);
310
180
      return false;
311
869
    } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
312
113
      writeObjCClassName(ID, FrontendBufOS);
313
756
    } else {
314
756
      return true;
315
756
    }
316
452
317
452
    // Now apply backend mangling.
318
452
    llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
319
452
    return false;
320
452
  }
321
322
128
  std::string getName(const Decl *D) {
323
128
    std::string Name;
324
128
    {
325
128
      llvm::raw_string_ostream OS(Name);
326
128
      writeName(D, OS);
327
128
    }
328
128
    return Name;
329
128
  }
330
331
  enum ObjCKind {
332
    ObjCClass,
333
    ObjCMetaclass,
334
  };
335
336
  static StringRef getClassSymbolPrefix(ObjCKind Kind,
337
121
                                        const ASTContext &Context) {
338
121
    if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
339
4
      return Kind == ObjCMetaclass ? 
"_OBJC_METACLASS_"2
:
"_OBJC_CLASS_"2
;
340
117
    return Kind == ObjCMetaclass ? 
"OBJC_METACLASS_$_"2
:
"OBJC_CLASS_$_"115
;
341
117
  }
342
343
4
  std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) {
344
4
    StringRef ClassName;
345
4
    if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
346
2
      ClassName = OID->getObjCRuntimeNameAsString();
347
2
    else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
348
2
      ClassName = OID->getObjCRuntimeNameAsString();
349
4
350
4
    if (ClassName.empty())
351
0
      return {};
352
4
353
8
    
auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string 4
{
354
8
      SmallString<40> Mangled;
355
8
      auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
356
8
      llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
357
8
      return Mangled.str();
358
8
    };
359
4
360
4
    return {
361
4
        Mangle(ObjCClass, ClassName),
362
4
        Mangle(ObjCMetaclass, ClassName),
363
4
    };
364
4
  }
365
366
170
  std::vector<std::string> getAllManglings(const Decl *D) {
367
170
    if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
368
4
      return getAllManglings(OCD);
369
166
370
166
    if (!(isa<CXXRecordDecl>(D) || 
isa<CXXMethodDecl>(D)145
))
371
82
      return {};
372
84
373
84
    const NamedDecl *ND = cast<NamedDecl>(D);
374
84
375
84
    ASTContext &Ctx = ND->getASTContext();
376
84
    std::unique_ptr<MangleContext> M(Ctx.createMangleContext());
377
84
378
84
    std::vector<std::string> Manglings;
379
84
380
84
    auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
381
1
      auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
382
1
                                                     /*IsCXXMethod=*/true);
383
1
      auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
384
1
      return CC == DefaultCC;
385
1
    };
386
84
387
84
    if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
388
22
      Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));
389
22
390
22
      if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
391
18
        if (!CD->getParent()->isAbstract())
392
16
          Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));
393
22
394
22
      if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
395
4
        if (CD->hasAttr<DLLExportAttr>() && 
CD->isDefaultConstructor()1
)
396
1
          if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
397
1
            Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
398
62
    } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
399
15
      Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
400
15
      if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
401
12
        Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
402
12
        if (DD->isVirtual())
403
10
          Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
404
12
      }
405
47
    } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
406
26
      Manglings.emplace_back(getName(ND));
407
26
      if (MD->isVirtual())
408
20
        if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
409
3
          for (const auto &T : *TIV)
410
3
            Manglings.emplace_back(getMangledThunk(MD, T));
411
26
    }
412
84
413
84
    return Manglings;
414
84
  }
415
416
private:
417
339
  bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
418
339
    if (MC->shouldMangleDeclName(D)) {
419
217
      if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
420
18
        MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
421
199
      else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
422
4
        MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
423
195
      else
424
195
        MC->mangleName(D, OS);
425
217
      return false;
426
217
    } else {
427
122
      IdentifierInfo *II = D->getIdentifier();
428
122
      if (!II)
429
0
        return true;
430
122
      OS << II->getName();
431
122
      return false;
432
122
    }
433
339
  }
434
435
113
  void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) {
436
113
    OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
437
113
    OS << D->getObjCRuntimeNameAsString();
438
113
  }
439
440
76
  std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) {
441
76
    std::string FrontendBuf;
442
76
    llvm::raw_string_ostream FOS(FrontendBuf);
443
76
444
76
    if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
445
39
      MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
446
37
    else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
447
37
      MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);
448
76
449
76
    std::string BackendBuf;
450
76
    llvm::raw_string_ostream BOS(BackendBuf);
451
76
452
76
    llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
453
76
454
76
    return BOS.str();
455
76
  }
456
457
3
  std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) {
458
3
    std::string FrontendBuf;
459
3
    llvm::raw_string_ostream FOS(FrontendBuf);
460
3
461
3
    MC->mangleThunk(MD, T, FOS);
462
3
463
3
    std::string BackendBuf;
464
3
    llvm::raw_string_ostream BOS(BackendBuf);
465
3
466
3
    llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);
467
3
468
3
    return BOS.str();
469
3
  }
470
};
471
472
ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)
473
227
    : Impl(llvm::make_unique<Implementation>(Ctx)) {}
474
475
227
ASTNameGenerator::~ASTNameGenerator() {}
476
477
1.32k
bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
478
1.32k
  return Impl->writeName(D, OS);
479
1.32k
}
480
481
102
std::string ASTNameGenerator::getName(const Decl *D) {
482
102
  return Impl->getName(D);
483
102
}
484
485
170
std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {
486
170
  return Impl->getAllManglings(D);
487
170
}