Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/InstallAPI/Visitor.cpp
35233 views
1
//===- Visitor.cpp ---------------------------------------------*- 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
#include "clang/InstallAPI/Visitor.h"
10
#include "clang/AST/Availability.h"
11
#include "clang/AST/ParentMapContext.h"
12
#include "clang/AST/VTableBuilder.h"
13
#include "clang/Basic/Linkage.h"
14
#include "clang/InstallAPI/DylibVerifier.h"
15
#include "clang/InstallAPI/FrontendRecords.h"
16
#include "llvm/ADT/SmallString.h"
17
#include "llvm/ADT/StringRef.h"
18
#include "llvm/IR/DataLayout.h"
19
#include "llvm/IR/Mangler.h"
20
21
using namespace llvm;
22
using namespace llvm::MachO;
23
24
namespace {
25
enum class CXXLinkage {
26
ExternalLinkage,
27
LinkOnceODRLinkage,
28
WeakODRLinkage,
29
PrivateLinkage,
30
};
31
}
32
33
namespace clang::installapi {
34
35
// Exported NamedDecl needs to have external linkage and
36
// default visibility from LinkageComputer.
37
static bool isExported(const NamedDecl *D) {
38
auto LV = D->getLinkageAndVisibility();
39
return isExternallyVisible(LV.getLinkage()) &&
40
(LV.getVisibility() == DefaultVisibility);
41
}
42
43
static bool isInlined(const FunctionDecl *D) {
44
bool HasInlineAttribute = false;
45
bool NoCXXAttr =
46
(!D->getASTContext().getLangOpts().CPlusPlus &&
47
!D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
48
!D->hasAttr<DLLExportAttr>());
49
50
// Check all redeclarations to find an inline attribute or keyword.
51
for (const auto *RD : D->redecls()) {
52
if (!RD->isInlined())
53
continue;
54
HasInlineAttribute = true;
55
if (!(NoCXXAttr || RD->hasAttr<GNUInlineAttr>()))
56
continue;
57
if (RD->doesThisDeclarationHaveABody() &&
58
RD->isInlineDefinitionExternallyVisible())
59
return false;
60
}
61
62
if (!HasInlineAttribute)
63
return false;
64
65
return true;
66
}
67
68
static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal = false) {
69
SymbolFlags Result = SymbolFlags::None;
70
if (WeakDef)
71
Result |= SymbolFlags::WeakDefined;
72
if (ThreadLocal)
73
Result |= SymbolFlags::ThreadLocalValue;
74
75
return Result;
76
}
77
78
void InstallAPIVisitor::HandleTranslationUnit(ASTContext &ASTCtx) {
79
if (ASTCtx.getDiagnostics().hasErrorOccurred())
80
return;
81
82
auto *D = ASTCtx.getTranslationUnitDecl();
83
TraverseDecl(D);
84
}
85
86
std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
87
SmallString<256> Name;
88
if (MC->shouldMangleDeclName(D)) {
89
raw_svector_ostream NStream(Name);
90
MC->mangleName(D, NStream);
91
} else
92
Name += D->getNameAsString();
93
94
return getBackendMangledName(Name);
95
}
96
97
std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
98
SmallString<256> FinalName;
99
Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
100
return std::string(FinalName);
101
}
102
103
std::optional<HeaderType>
104
InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {
105
SourceLocation Loc = D->getLocation();
106
if (Loc.isInvalid())
107
return std::nullopt;
108
109
// If the loc refers to a macro expansion, InstallAPI needs to first get the
110
// file location of the expansion.
111
auto FileLoc = SrcMgr.getFileLoc(Loc);
112
FileID ID = SrcMgr.getFileID(FileLoc);
113
if (ID.isInvalid())
114
return std::nullopt;
115
116
const FileEntry *FE = SrcMgr.getFileEntryForID(ID);
117
if (!FE)
118
return std::nullopt;
119
120
auto Header = Ctx.findAndRecordFile(FE, PP);
121
if (!Header.has_value())
122
return std::nullopt;
123
124
HeaderType Access = Header.value();
125
assert(Access != HeaderType::Unknown && "unexpected access level for global");
126
return Access;
127
}
128
129
/// Check if the interface itself or any of its super classes have an
130
/// exception attribute. InstallAPI needs to export an additional symbol
131
/// ("OBJC_EHTYPE_$CLASS_NAME") if any of the classes have the exception
132
/// attribute.
133
static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D) {
134
for (; D != nullptr; D = D->getSuperClass())
135
if (D->hasAttr<ObjCExceptionAttr>())
136
return true;
137
138
return false;
139
}
140
void InstallAPIVisitor::recordObjCInstanceVariables(
141
const ASTContext &ASTCtx, ObjCContainerRecord *Record, StringRef SuperClass,
142
const llvm::iterator_range<
143
DeclContext::specific_decl_iterator<ObjCIvarDecl>>
144
Ivars) {
145
RecordLinkage Linkage = RecordLinkage::Exported;
146
const RecordLinkage ContainerLinkage = Record->getLinkage();
147
// If fragile, set to unknown.
148
if (ASTCtx.getLangOpts().ObjCRuntime.isFragile())
149
Linkage = RecordLinkage::Unknown;
150
// Linkage should be inherited from container.
151
else if (ContainerLinkage != RecordLinkage::Unknown)
152
Linkage = ContainerLinkage;
153
for (const auto *IV : Ivars) {
154
auto Access = getAccessForDecl(IV);
155
if (!Access)
156
continue;
157
StringRef Name = IV->getName();
158
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(IV);
159
auto AC = IV->getCanonicalAccessControl();
160
auto [ObjCIVR, FA] =
161
Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC);
162
Ctx.Verifier->verify(ObjCIVR, FA, SuperClass);
163
}
164
}
165
166
bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
167
// Skip forward declaration for classes (@class)
168
if (!D->isThisDeclarationADefinition())
169
return true;
170
171
// Skip over declarations that access could not be collected for.
172
auto Access = getAccessForDecl(D);
173
if (!Access)
174
return true;
175
176
StringRef Name = D->getObjCRuntimeNameAsString();
177
const RecordLinkage Linkage =
178
isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
179
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
180
const bool IsEHType =
181
(!D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
182
hasObjCExceptionAttribute(D));
183
184
auto [Class, FA] =
185
Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
186
Ctx.Verifier->verify(Class, FA);
187
188
// Get base class.
189
StringRef SuperClassName;
190
if (const auto *SuperClass = D->getSuperClass())
191
SuperClassName = SuperClass->getObjCRuntimeNameAsString();
192
193
recordObjCInstanceVariables(D->getASTContext(), Class, Class->getName(),
194
D->ivars());
195
return true;
196
}
197
198
bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
199
StringRef CategoryName = D->getName();
200
// Skip over declarations that access could not be collected for.
201
auto Access = getAccessForDecl(D);
202
if (!Access)
203
return true;
204
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
205
const ObjCInterfaceDecl *InterfaceD = D->getClassInterface();
206
const StringRef InterfaceName = InterfaceD->getName();
207
208
ObjCCategoryRecord *CategoryRecord =
209
Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access)
210
.first;
211
recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName,
212
D->ivars());
213
return true;
214
}
215
216
bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
217
// Skip function parameters.
218
if (isa<ParmVarDecl>(D))
219
return true;
220
221
// Skip variables in records. They are handled separately for C++.
222
if (D->getDeclContext()->isRecord())
223
return true;
224
225
// Skip anything inside functions or methods.
226
if (!D->isDefinedOutsideFunctionOrMethod())
227
return true;
228
229
// If this is a template but not specialization or instantiation, skip.
230
if (D->getASTContext().getTemplateOrSpecializationInfo(D) &&
231
D->getTemplateSpecializationKind() == TSK_Undeclared)
232
return true;
233
234
// Skip over declarations that access could not collected for.
235
auto Access = getAccessForDecl(D);
236
if (!Access)
237
return true;
238
239
const RecordLinkage Linkage =
240
isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
241
const bool WeakDef = D->hasAttr<WeakAttr>();
242
const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None;
243
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
244
auto [GR, FA] = Ctx.Slice->addGlobal(getMangledName(D), Linkage,
245
GlobalRecord::Kind::Variable, Avail, D,
246
*Access, getFlags(WeakDef, ThreadLocal));
247
Ctx.Verifier->verify(GR, FA);
248
return true;
249
}
250
251
bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) {
252
if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(D)) {
253
// Skip member function in class templates.
254
if (M->getParent()->getDescribedClassTemplate() != nullptr)
255
return true;
256
257
// Skip methods in CXX RecordDecls.
258
for (const DynTypedNode &P : D->getASTContext().getParents(*M)) {
259
if (P.get<CXXRecordDecl>())
260
return true;
261
}
262
263
// Skip CXX ConstructorDecls and DestructorDecls.
264
if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M))
265
return true;
266
}
267
268
// Skip templated functions.
269
switch (D->getTemplatedKind()) {
270
case FunctionDecl::TK_NonTemplate:
271
case FunctionDecl::TK_DependentNonTemplate:
272
break;
273
case FunctionDecl::TK_MemberSpecialization:
274
case FunctionDecl::TK_FunctionTemplateSpecialization:
275
if (auto *TempInfo = D->getTemplateSpecializationInfo()) {
276
if (!TempInfo->isExplicitInstantiationOrSpecialization())
277
return true;
278
}
279
break;
280
case FunctionDecl::TK_FunctionTemplate:
281
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
282
return true;
283
}
284
285
auto Access = getAccessForDecl(D);
286
if (!Access)
287
return true;
288
auto Name = getMangledName(D);
289
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
290
const bool ExplicitInstantiation = D->getTemplateSpecializationKind() ==
291
TSK_ExplicitInstantiationDeclaration;
292
const bool WeakDef = ExplicitInstantiation || D->hasAttr<WeakAttr>();
293
const bool Inlined = isInlined(D);
294
const RecordLinkage Linkage = (Inlined || !isExported(D))
295
? RecordLinkage::Internal
296
: RecordLinkage::Exported;
297
auto [GR, FA] =
298
Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail,
299
D, *Access, getFlags(WeakDef), Inlined);
300
Ctx.Verifier->verify(GR, FA);
301
return true;
302
}
303
304
static bool hasVTable(const CXXRecordDecl *D) {
305
// Check if vtable symbols should be emitted, only dynamic classes need
306
// vtables.
307
if (!D->hasDefinition() || !D->isDynamicClass())
308
return false;
309
310
assert(D->isExternallyVisible() && "Should be externally visible");
311
assert(D->isCompleteDefinition() && "Only works on complete definitions");
312
313
const CXXMethodDecl *KeyFunctionD =
314
D->getASTContext().getCurrentKeyFunction(D);
315
// If this class has a key function, then there is a vtable, possibly internal
316
// though.
317
if (KeyFunctionD) {
318
switch (KeyFunctionD->getTemplateSpecializationKind()) {
319
case TSK_Undeclared:
320
case TSK_ExplicitSpecialization:
321
case TSK_ImplicitInstantiation:
322
case TSK_ExplicitInstantiationDefinition:
323
return true;
324
case TSK_ExplicitInstantiationDeclaration:
325
llvm_unreachable(
326
"Unexpected TemplateSpecializationKind for key function");
327
}
328
} else if (D->isAbstract()) {
329
// If the class is abstract and it doesn't have a key function, it is a
330
// 'pure' virtual class. It doesn't need a vtable.
331
return false;
332
}
333
334
switch (D->getTemplateSpecializationKind()) {
335
case TSK_Undeclared:
336
case TSK_ExplicitSpecialization:
337
case TSK_ImplicitInstantiation:
338
return false;
339
340
case TSK_ExplicitInstantiationDeclaration:
341
case TSK_ExplicitInstantiationDefinition:
342
return true;
343
}
344
345
llvm_unreachable("Invalid TemplateSpecializationKind!");
346
}
347
348
static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) {
349
assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable");
350
assert(D->isExternallyVisible() && "Record should be externally visible");
351
if (D->getVisibility() == HiddenVisibility)
352
return CXXLinkage::PrivateLinkage;
353
354
const CXXMethodDecl *KeyFunctionD =
355
D->getASTContext().getCurrentKeyFunction(D);
356
if (KeyFunctionD) {
357
// If this class has a key function, use that to determine the
358
// linkage of the vtable.
359
switch (KeyFunctionD->getTemplateSpecializationKind()) {
360
case TSK_Undeclared:
361
case TSK_ExplicitSpecialization:
362
if (isInlined(KeyFunctionD))
363
return CXXLinkage::LinkOnceODRLinkage;
364
return CXXLinkage::ExternalLinkage;
365
case TSK_ImplicitInstantiation:
366
llvm_unreachable("No external vtable for implicit instantiations");
367
case TSK_ExplicitInstantiationDefinition:
368
return CXXLinkage::WeakODRLinkage;
369
case TSK_ExplicitInstantiationDeclaration:
370
llvm_unreachable(
371
"Unexpected TemplateSpecializationKind for key function");
372
}
373
}
374
375
switch (D->getTemplateSpecializationKind()) {
376
case TSK_Undeclared:
377
case TSK_ExplicitSpecialization:
378
case TSK_ImplicitInstantiation:
379
return CXXLinkage::LinkOnceODRLinkage;
380
case TSK_ExplicitInstantiationDeclaration:
381
case TSK_ExplicitInstantiationDefinition:
382
return CXXLinkage::WeakODRLinkage;
383
}
384
385
llvm_unreachable("Invalid TemplateSpecializationKind!");
386
}
387
388
static bool isRTTIWeakDef(const CXXRecordDecl *D) {
389
if (D->hasAttr<WeakAttr>())
390
return true;
391
392
if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr)
393
return true;
394
395
if (D->isDynamicClass())
396
return getVTableLinkage(D) != CXXLinkage::ExternalLinkage;
397
398
return false;
399
}
400
401
static bool hasRTTI(const CXXRecordDecl *D) {
402
if (!D->getASTContext().getLangOpts().RTTI)
403
return false;
404
405
if (!D->hasDefinition())
406
return false;
407
408
if (!D->isDynamicClass())
409
return false;
410
411
// Don't emit weak-def RTTI information. InstallAPI cannot reliably determine
412
// if the final binary will have those weak defined RTTI symbols. This depends
413
// on the optimization level and if the class has been instantiated and used.
414
//
415
// Luckily, the Apple static linker doesn't need those weak defined RTTI
416
// symbols for linking. They are only needed by the runtime linker. That means
417
// they can be safely dropped.
418
if (isRTTIWeakDef(D))
419
return false;
420
421
return true;
422
}
423
424
std::string
425
InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
426
SmallString<256> Name;
427
raw_svector_ostream NameStream(Name);
428
MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream);
429
430
return getBackendMangledName(Name);
431
}
432
433
std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
434
SmallString<256> Name;
435
raw_svector_ostream NameStream(Name);
436
MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream);
437
438
return getBackendMangledName(Name);
439
}
440
441
std::string
442
InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const {
443
SmallString<256> Name;
444
raw_svector_ostream NameStream(Name);
445
MC->mangleCXXVTable(D, NameStream);
446
447
return getBackendMangledName(Name);
448
}
449
450
std::string InstallAPIVisitor::getMangledCXXThunk(
451
const GlobalDecl &D, const ThunkInfo &Thunk, bool ElideOverrideInfo) const {
452
SmallString<256> Name;
453
raw_svector_ostream NameStream(Name);
454
const auto *Method = cast<CXXMethodDecl>(D.getDecl());
455
if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(Method))
456
MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk, ElideOverrideInfo,
457
NameStream);
458
else
459
MC->mangleThunk(Method, Thunk, ElideOverrideInfo, NameStream);
460
461
return getBackendMangledName(Name);
462
}
463
464
std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D,
465
int Type) const {
466
SmallString<256> Name;
467
raw_svector_ostream NameStream(Name);
468
GlobalDecl GD;
469
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(D))
470
GD = GlobalDecl(Ctor, CXXCtorType(Type));
471
else {
472
const auto *Dtor = cast<CXXDestructorDecl>(D);
473
GD = GlobalDecl(Dtor, CXXDtorType(Type));
474
}
475
MC->mangleName(GD, NameStream);
476
return getBackendMangledName(Name);
477
}
478
479
void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
480
const AvailabilityInfo &Avail,
481
const HeaderType Access,
482
bool EmittedVTable) {
483
if (hasVTable(D)) {
484
EmittedVTable = true;
485
const CXXLinkage VTableLinkage = getVTableLinkage(D);
486
if (VTableLinkage == CXXLinkage::ExternalLinkage ||
487
VTableLinkage == CXXLinkage::WeakODRLinkage) {
488
const std::string Name = getMangledCXXVTableName(D);
489
const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;
490
auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
491
GlobalRecord::Kind::Variable, Avail,
492
D, Access, getFlags(WeakDef));
493
Ctx.Verifier->verify(GR, FA);
494
if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) {
495
VTableContextBase *VTable = D->getASTContext().getVTableContext();
496
auto AddThunk = [&](GlobalDecl GD) {
497
const ItaniumVTableContext::ThunkInfoVectorTy *Thunks =
498
VTable->getThunkInfo(GD);
499
if (!Thunks)
500
return;
501
502
for (const auto &Thunk : *Thunks) {
503
const std::string Name =
504
getMangledCXXThunk(GD, Thunk, /*ElideOverrideInfo=*/true);
505
auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
506
GlobalRecord::Kind::Function,
507
Avail, GD.getDecl(), Access);
508
Ctx.Verifier->verify(GR, FA);
509
}
510
};
511
512
for (const auto *Method : D->methods()) {
513
if (isa<CXXConstructorDecl>(Method) || !Method->isVirtual())
514
continue;
515
516
if (auto Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
517
// Skip default destructor.
518
if (Dtor->isDefaulted())
519
continue;
520
AddThunk({Dtor, Dtor_Deleting});
521
AddThunk({Dtor, Dtor_Complete});
522
} else
523
AddThunk(Method);
524
}
525
}
526
}
527
}
528
529
if (!EmittedVTable)
530
return;
531
532
if (hasRTTI(D)) {
533
std::string Name = getMangledCXXRTTI(D);
534
auto [GR, FA] =
535
Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
536
GlobalRecord::Kind::Variable, Avail, D, Access);
537
Ctx.Verifier->verify(GR, FA);
538
539
Name = getMangledCXXRTTIName(D);
540
auto [NamedGR, NamedFA] =
541
Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
542
GlobalRecord::Kind::Variable, Avail, D, Access);
543
Ctx.Verifier->verify(NamedGR, NamedFA);
544
}
545
546
for (const auto &It : D->bases()) {
547
const CXXRecordDecl *Base =
548
cast<CXXRecordDecl>(It.getType()->castAs<RecordType>()->getDecl());
549
const auto BaseAccess = getAccessForDecl(Base);
550
if (!BaseAccess)
551
continue;
552
const AvailabilityInfo BaseAvail = AvailabilityInfo::createFromDecl(Base);
553
emitVTableSymbols(Base, BaseAvail, *BaseAccess, /*EmittedVTable=*/true);
554
}
555
}
556
557
bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) {
558
if (!D->isCompleteDefinition())
559
return true;
560
561
// Skip templated classes.
562
if (D->getDescribedClassTemplate() != nullptr)
563
return true;
564
565
// Skip partial templated classes too.
566
if (isa<ClassTemplatePartialSpecializationDecl>(D))
567
return true;
568
569
auto Access = getAccessForDecl(D);
570
if (!Access)
571
return true;
572
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
573
574
// Check whether to emit the vtable/rtti symbols.
575
if (isExported(D))
576
emitVTableSymbols(D, Avail, *Access);
577
578
TemplateSpecializationKind ClassSK = TSK_Undeclared;
579
bool KeepInlineAsWeak = false;
580
if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
581
ClassSK = Templ->getTemplateSpecializationKind();
582
if (ClassSK == TSK_ExplicitInstantiationDeclaration)
583
KeepInlineAsWeak = true;
584
}
585
586
// Record the class methods.
587
for (const auto *M : D->methods()) {
588
// Inlined methods are usually not emitted, except when it comes from a
589
// specialized template.
590
bool WeakDef = false;
591
if (isInlined(M)) {
592
if (!KeepInlineAsWeak)
593
continue;
594
595
WeakDef = true;
596
}
597
598
if (!isExported(M))
599
continue;
600
601
switch (M->getTemplateSpecializationKind()) {
602
case TSK_Undeclared:
603
case TSK_ExplicitSpecialization:
604
break;
605
case TSK_ImplicitInstantiation:
606
continue;
607
case TSK_ExplicitInstantiationDeclaration:
608
if (ClassSK == TSK_ExplicitInstantiationDeclaration)
609
WeakDef = true;
610
break;
611
case TSK_ExplicitInstantiationDefinition:
612
WeakDef = true;
613
break;
614
}
615
616
if (!M->isUserProvided())
617
continue;
618
619
// Methods that are deleted are not exported.
620
if (M->isDeleted())
621
continue;
622
623
const auto Access = getAccessForDecl(M);
624
if (!Access)
625
return true;
626
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(M);
627
628
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(M)) {
629
// Defaulted constructors are not exported.
630
if (Ctor->isDefaulted())
631
continue;
632
633
std::string Name = getMangledCtorDtor(M, Ctor_Base);
634
auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
635
GlobalRecord::Kind::Function, Avail,
636
D, *Access, getFlags(WeakDef));
637
Ctx.Verifier->verify(GR, FA);
638
639
if (!D->isAbstract()) {
640
std::string Name = getMangledCtorDtor(M, Ctor_Complete);
641
auto [GR, FA] = Ctx.Slice->addGlobal(
642
Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
643
D, *Access, getFlags(WeakDef));
644
Ctx.Verifier->verify(GR, FA);
645
}
646
647
continue;
648
}
649
650
if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(M)) {
651
// Defaulted destructors are not exported.
652
if (Dtor->isDefaulted())
653
continue;
654
655
std::string Name = getMangledCtorDtor(M, Dtor_Base);
656
auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
657
GlobalRecord::Kind::Function, Avail,
658
D, *Access, getFlags(WeakDef));
659
Ctx.Verifier->verify(GR, FA);
660
661
Name = getMangledCtorDtor(M, Dtor_Complete);
662
auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal(
663
Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D,
664
*Access, getFlags(WeakDef));
665
Ctx.Verifier->verify(CompleteGR, CompleteFA);
666
667
if (Dtor->isVirtual()) {
668
Name = getMangledCtorDtor(M, Dtor_Deleting);
669
auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal(
670
Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
671
D, *Access, getFlags(WeakDef));
672
Ctx.Verifier->verify(VirtualGR, VirtualFA);
673
}
674
675
continue;
676
}
677
678
// Though abstract methods can map to exports, this is generally unexpected.
679
// Except in the case of destructors. Only ignore pure virtuals after
680
// checking if the member function was a destructor.
681
if (M->isPureVirtual())
682
continue;
683
684
std::string Name = getMangledName(M);
685
auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
686
GlobalRecord::Kind::Function, Avail, M,
687
*Access, getFlags(WeakDef));
688
Ctx.Verifier->verify(GR, FA);
689
}
690
691
if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
692
if (!Templ->isExplicitInstantiationOrSpecialization())
693
return true;
694
}
695
696
using var_iter = CXXRecordDecl::specific_decl_iterator<VarDecl>;
697
using var_range = iterator_range<var_iter>;
698
for (const auto *Var : var_range(D->decls())) {
699
// Skip const static member variables.
700
// \code
701
// struct S {
702
// static const int x = 0;
703
// };
704
// \endcode
705
if (Var->isStaticDataMember() && Var->hasInit())
706
continue;
707
708
// Skip unexported var decls.
709
if (!isExported(Var))
710
continue;
711
712
const std::string Name = getMangledName(Var);
713
const auto Access = getAccessForDecl(Var);
714
if (!Access)
715
return true;
716
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var);
717
const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak;
718
719
auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
720
GlobalRecord::Kind::Variable, Avail, D,
721
*Access, getFlags(WeakDef));
722
Ctx.Verifier->verify(GR, FA);
723
}
724
725
return true;
726
}
727
728
} // namespace clang::installapi
729
730