Coverage Report

Created: 2020-02-25 14:32

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