clang: lib/InstallAPI/Visitor.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
16#include "llvm/ADT/StringRef.h"
17#include "llvm/IR/DataLayout.h"
18#include "llvm/IR/Mangler.h"
19
20using namespace llvm;
22
23namespace {
24enum class CXXLinkage {
25 ExternalLinkage,
26 LinkOnceODRLinkage,
27 WeakODRLinkage,
28 PrivateLinkage,
29};
30}
31
33
34
35
41
43 bool HasInlineAttribute = false;
44 bool NoCXXAttr =
47 !D->hasAttr());
48
49
50 for (const auto *RD : D->redecls()) {
51 if (!RD->isInlined())
52 continue;
53 HasInlineAttribute = true;
54 if (!(NoCXXAttr || RD->hasAttr()))
55 continue;
56 if (RD->doesThisDeclarationHaveABody() &&
57 RD->isInlineDefinitionExternallyVisible())
58 return false;
59 }
60
61 if (!HasInlineAttribute)
62 return false;
63
64 return true;
65}
66
69 if (WeakDef)
70 Result |= SymbolFlags::WeakDefined;
71 if (ThreadLocal)
72 Result |= SymbolFlags::ThreadLocalValue;
73
75}
76
84
85std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
87 if (MC->shouldMangleDeclName(D)) {
88 raw_svector_ostream NStream(Name);
89 MC->mangleName(D, NStream);
90 } else
92
93 return getBackendMangledName(Name);
94}
95
96std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
98 Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
99 return std::string(FinalName);
100}
101
102std::optional
103InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {
104 SourceLocation Loc = D->getLocation();
105 if (Loc.isInvalid())
106 return std::nullopt;
107
108
109
110 auto FileLoc = SrcMgr.getFileLoc(Loc);
111 FileID ID = SrcMgr.getFileID(FileLoc);
112 if (ID.isInvalid())
113 return std::nullopt;
114
115 const FileEntry *FE = SrcMgr.getFileEntryForID(ID);
116 if (!FE)
117 return std::nullopt;
118
119 auto Header = Ctx.findAndRecordFile(FE, PP);
120 if (!Header.has_value())
121 return std::nullopt;
122
124 assert(Access != HeaderType::Unknown && "unexpected access level for global");
125 return Access;
126}
127
128
129
130
131
134 if (D->hasAttr())
135 return true;
136
137 return false;
138}
139void InstallAPIVisitor::recordObjCInstanceVariables(
141 const llvm::iterator_range<
143 Ivars) {
146
148 Linkage = RecordLinkage::Unknown;
149
150 else if (ContainerLinkage != RecordLinkage::Unknown)
151 Linkage = ContainerLinkage;
152 for (const auto *IV : Ivars) {
153 auto Access = getAccessForDecl(IV);
154 if (!Access)
155 continue;
156 StringRef Name = IV->getName();
158 auto AC = IV->getCanonicalAccessControl();
159 auto [ObjCIVR, FA] =
160 Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC);
161 Ctx.Verifier->verify(ObjCIVR, FA, SuperClass);
162 }
163}
164
166
168 return true;
169
170
171 auto Access = getAccessForDecl(D);
172 if (!Access)
173 return true;
174
177 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
179 const bool IsEHType =
182
183 auto [Class, FA] =
184 Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
185 Ctx.Verifier->verify(Class, FA);
186
187
188 StringRef SuperClassName;
190 SuperClassName = SuperClass->getObjCRuntimeNameAsString();
191
194 return true;
195}
196
198 StringRef CategoryName = D->getName();
199
200 auto Access = getAccessForDecl(D);
201 if (!Access)
202 return true;
205 const StringRef InterfaceName = InterfaceD->getName();
206
208 Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access)
209 .first;
210 recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName,
212 return true;
213}
214
216
218 return true;
219
220
222 return true;
223
224
226 return true;
227
228
231 return true;
232
233
234 auto Access = getAccessForDecl(D);
235 if (!Access)
236 return true;
237
239 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
240 const bool WeakDef = D->hasAttr();
243 auto [GR, FA] = Ctx.Slice->addGlobal(getMangledName(D), Linkage,
244 GlobalRecord::Kind::Variable, Avail, D,
245 *Access, getFlags(WeakDef, ThreadLocal));
246 Ctx.Verifier->verify(GR, FA);
247 return true;
248}
249
251 if (const CXXMethodDecl *M = dyn_cast(D)) {
252
253 if (M->getParent()->getDescribedClassTemplate() != nullptr)
254 return true;
255
256
259 return true;
260 }
261
262
264 return true;
265 }
266
267
271 break;
275 if (!TempInfo->isExplicitInstantiationOrSpecialization())
276 return true;
277 }
278 break;
281 return true;
282 }
283
284 auto Access = getAccessForDecl(D);
285 if (!Access)
286 return true;
287 auto Name = getMangledName(D);
292 const bool Inlined = isInlined(D);
294 ? RecordLinkage::Internal
295 : RecordLinkage::Exported;
296 auto [GR, FA] =
297 Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail,
298 D, *Access, getFlags(WeakDef), Inlined);
299 Ctx.Verifier->verify(GR, FA);
300 return true;
301}
302
304
305
307 return false;
308
311
314
315
316 if (KeyFunctionD) {
322 return true;
324 llvm_unreachable(
325 "Unexpected TemplateSpecializationKind for key function");
326 }
328
329
330 return false;
331 }
332
337 return false;
338
341 return true;
342 }
343
344 llvm_unreachable("Invalid TemplateSpecializationKind!");
345}
346
349 assert(D->isExternallyVisible() && "Record should be externally visible");
351 return CXXLinkage::PrivateLinkage;
352
355 if (KeyFunctionD) {
356
357
362 return CXXLinkage::LinkOnceODRLinkage;
363 return CXXLinkage::ExternalLinkage;
365 llvm_unreachable("No external vtable for implicit instantiations");
367 return CXXLinkage::WeakODRLinkage;
369 llvm_unreachable(
370 "Unexpected TemplateSpecializationKind for key function");
371 }
372 }
373
378 return CXXLinkage::LinkOnceODRLinkage;
381 return CXXLinkage::WeakODRLinkage;
382 }
383
384 llvm_unreachable("Invalid TemplateSpecializationKind!");
385}
386
388 if (D->hasAttr())
389 return true;
390
392 return true;
393
396
397 return false;
398}
399
402 return false;
403
405 return false;
406
408 return false;
409
410
411
412
413
414
415
416
418 return false;
419
420 return true;
421}
422
423std::string
424InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
426 raw_svector_ostream NameStream(Name);
427 MC->mangleCXXRTTIName(MC->getASTContext().getCanonicalTagType(D), NameStream);
428
429 return getBackendMangledName(Name);
430}
431
432std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
434 raw_svector_ostream NameStream(Name);
435 MC->mangleCXXRTTI(MC->getASTContext().getCanonicalTagType(D), NameStream);
436
437 return getBackendMangledName(Name);
438}
439
440std::string
441InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const {
442 SmallString<256> Name;
443 raw_svector_ostream NameStream(Name);
444 MC->mangleCXXVTable(D, NameStream);
445
446 return getBackendMangledName(Name);
447}
448
449std::string InstallAPIVisitor::getMangledCXXThunk(
450 const GlobalDecl &D, const ThunkInfo &Thunk, bool ElideOverrideInfo) const {
451 SmallString<256> Name;
452 raw_svector_ostream NameStream(Name);
454 if (const auto *Dtor = dyn_cast(Method))
455 MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk, ElideOverrideInfo,
456 NameStream);
457 else
458 MC->mangleThunk(Method, Thunk, ElideOverrideInfo, NameStream);
459
460 return getBackendMangledName(Name);
461}
462
463std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D,
464 int Type) const {
465 SmallString<256> Name;
466 raw_svector_ostream NameStream(Name);
467 GlobalDecl GD;
468 if (const auto *Ctor = dyn_cast(D))
470 else {
473 }
474 MC->mangleName(GD, NameStream);
475 return getBackendMangledName(Name);
476}
477
478void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
479 const AvailabilityInfo &Avail,
481 bool EmittedVTable) {
483 EmittedVTable = true;
485 if (VTableLinkage == CXXLinkage::ExternalLinkage ||
486 VTableLinkage == CXXLinkage::WeakODRLinkage) {
487 const std::string Name = getMangledCXXVTableName(D);
488 const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;
489 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
490 GlobalRecord::Kind::Variable, Avail,
491 D, Access, getFlags(WeakDef));
492 Ctx.Verifier->verify(GR, FA);
493 if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) {
494 VTableContextBase *VTable = D->getASTContext().getVTableContext();
495 auto AddThunk = [&](GlobalDecl GD) {
497 VTable->getThunkInfo(GD);
498 if (!Thunks)
499 return;
500
501 for (const auto &Thunk : *Thunks) {
502 const std::string Name =
503 getMangledCXXThunk(GD, Thunk, true);
504 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
505 GlobalRecord::Kind::Function,
506 Avail, GD.getDecl(), Access);
507 Ctx.Verifier->verify(GR, FA);
508 }
509 };
510
511 for (const auto *Method : D->methods()) {
513 continue;
514
515 if (auto Dtor = dyn_cast(Method)) {
516
517 if (Dtor->isDefaulted())
518 continue;
521 } else
523 }
524 }
525 }
526 }
527
528 if (!EmittedVTable)
529 return;
530
532 std::string Name = getMangledCXXRTTI(D);
533 auto [GR, FA] =
534 Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
535 GlobalRecord::Kind::Variable, Avail, D, Access);
536 Ctx.Verifier->verify(GR, FA);
537
538 Name = getMangledCXXRTTIName(D);
539 auto [NamedGR, NamedFA] =
540 Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
541 GlobalRecord::Kind::Variable, Avail, D, Access);
542 Ctx.Verifier->verify(NamedGR, NamedFA);
543 }
544
545 for (const auto &It : D->bases()) {
546 const auto *Base =
548 const auto BaseAccess = getAccessForDecl(Base);
549 if (!BaseAccess)
550 continue;
552 emitVTableSymbols(Base, BaseAvail, *BaseAccess, true);
553 }
554}
555
558 return true;
559
560
562 return true;
563
564
566 return true;
567
568 auto Access = getAccessForDecl(D);
569 if (!Access)
570 return true;
572
573
575 emitVTableSymbols(D, Avail, *Access);
576
578 bool KeepInlineAsWeak = false;
579 if (auto *Templ = dyn_cast(D)) {
580 ClassSK = Templ->getTemplateSpecializationKind();
582 KeepInlineAsWeak = true;
583 }
584
585
586 for (const auto *M : D->methods()) {
587
588
589 bool WeakDef = false;
591 if (!KeepInlineAsWeak)
592 continue;
593
594 WeakDef = true;
595 }
596
598 continue;
599
600 switch (M->getTemplateSpecializationKind()) {
603 break;
605 continue;
608 WeakDef = true;
609 break;
611 WeakDef = true;
612 break;
613 }
614
615 if (!M->isUserProvided())
616 continue;
617
618
619 if (M->isDeleted())
620 continue;
621
622 const auto Access = getAccessForDecl(M);
623 if (!Access)
624 return true;
626
627 if (const auto *Ctor = dyn_cast(M)) {
628
629 if (Ctor->isDefaulted())
630 continue;
631
632 std::string Name = getMangledCtorDtor(M, Ctor_Base);
633 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
634 GlobalRecord::Kind::Function, Avail,
635 D, *Access, getFlags(WeakDef));
636 Ctx.Verifier->verify(GR, FA);
637
639 std::string Name = getMangledCtorDtor(M, Ctor_Complete);
640 auto [GR, FA] = Ctx.Slice->addGlobal(
641 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
642 D, *Access, getFlags(WeakDef));
643 Ctx.Verifier->verify(GR, FA);
644 }
645
646 continue;
647 }
648
649 if (const auto *Dtor = dyn_cast(M)) {
650
651 if (Dtor->isDefaulted())
652 continue;
653
654 std::string Name = getMangledCtorDtor(M, Dtor_Base);
655 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
656 GlobalRecord::Kind::Function, Avail,
657 D, *Access, getFlags(WeakDef));
658 Ctx.Verifier->verify(GR, FA);
659
661 auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal(
662 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D,
664 Ctx.Verifier->verify(CompleteGR, CompleteFA);
665
666 if (Dtor->isVirtual()) {
668 auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal(
669 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
670 D, *Access, getFlags(WeakDef));
671 Ctx.Verifier->verify(VirtualGR, VirtualFA);
672 }
673
674 continue;
675 }
676
677
678
679
680 if (M->isPureVirtual())
681 continue;
682
683 std::string Name = getMangledName(M);
684 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
685 GlobalRecord::Kind::Function, Avail, M,
687 Ctx.Verifier->verify(GR, FA);
688 }
689
690 if (auto *Templ = dyn_cast(D)) {
691 if (!Templ->isExplicitInstantiationOrSpecialization())
692 return true;
693 }
694
696 using var_range = iterator_range<var_iter>;
697 for (const auto *Var : var_range(D->decls())) {
698
699
700
701
702
703
704 if (Var->isStaticDataMember() && Var->hasInit())
705 continue;
706
707
709 continue;
710
711 const std::string Name = getMangledName(Var);
712 const auto Access = getAccessForDecl(Var);
713 if (!Access)
714 return true;
716 const bool WeakDef = Var->hasAttr() || KeepInlineAsWeak;
717
718 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
719 GlobalRecord::Kind::Variable, Avail, D,
721 Ctx.Verifier->verify(GR, FA);
722 }
723
724 return true;
725}
726
727}
llvm::MachO::SymbolFlags SymbolFlags
llvm::MachO::ObjCCategoryRecord ObjCCategoryRecord
llvm::MachO::RecordLinkage RecordLinkage
llvm::MachO::Record Record
llvm::MachO::ObjCContainerRecord ObjCContainerRecord
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
TemplateOrSpecializationInfo getTemplateOrSpecializationInfo(const VarDecl *Var)
DynTypedNodeList getParents(const NodeT &Node)
Forwards to get node parents from the ParentMapContext.
const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)
Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
method_range methods() const
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine whether this particular class is a specialization or instantiation of a class template or m...
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
bool hasDefinition() const
ClassTemplateDecl * getDescribedClassTemplate() const
Retrieves the class template that is described by this class declaration.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
ASTContext & getASTContext() const LLVM_READONLY
bool isDefinedOutsideFunctionOrMethod() const
isDefinedOutsideFunctionOrMethod - This predicate returns true if this scoped decl is defined outside...
DeclContext * getDeclContext()
bool hasErrorOccurred() const
A dynamically typed AST node container.
Represents a function declaration or definition.
FunctionTemplateSpecializationInfo * getTemplateSpecializationInfo() const
If this function is actually a function template specialization, retrieve information about this func...
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
@ TK_DependentFunctionTemplateSpecialization
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
clang::ObjCRuntime ObjCRuntime
This represents a decl that may have a name.
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Visibility getVisibility() const
Determines the visibility of this entity.
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
bool isExternallyVisible() const
ObjCCategoryDecl - Represents a category declaration.
ObjCInterfaceDecl * getClassInterface()
Represents an ObjC class declaration.
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
StringRef getObjCRuntimeNameAsString() const
Produce a name to be used for class's metadata.
ObjCInterfaceDecl * getSuperClass() const
The basic abstraction for the target Objective-C runtime.
bool isFragile() const
The inverse of isNonFragile(): does this runtime follow the set of implied behaviors for a "fragile" ...
bool TraverseDecl(Decl *D)
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
Represents a variable declaration or definition.
TLSKind getTLSKind() const
@ TLS_None
Not a TLS variable.
TemplateSpecializationKind getTemplateSpecializationKind() const
If this variable is an instantiation of a variable template or a static data member of a class templa...
void HandleTranslationUnit(ASTContext &ASTCtx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
Definition Visitor.cpp:77
bool VisitCXXRecordDecl(const CXXRecordDecl *D)
Collect global c++ declarations.
Definition Visitor.cpp:556
bool VisitFunctionDecl(const FunctionDecl *D)
Collect global functions.
Definition Visitor.cpp:250
bool VisitVarDecl(const VarDecl *D)
Collect global variables.
Definition Visitor.cpp:215
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D)
Collect Objective-C Category/Extension declarations.
Definition Visitor.cpp:197
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D)
Collect Objective-C Interface declarations.
Definition Visitor.cpp:165
Defines the Linkage enumeration and various utility functions.
The DirectoryScanner for collecting library files on the file system.
static bool isInlined(const FunctionDecl *D)
Definition Visitor.cpp:42
static CXXLinkage getVTableLinkage(const CXXRecordDecl *D)
Definition Visitor.cpp:347
@ Unknown
Unset or unknown type.
static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D)
Check if the interface itself or any of its super classes have an exception attribute.
Definition Visitor.cpp:132
static bool hasVTable(const CXXRecordDecl *D)
Definition Visitor.cpp:303
static bool isRTTIWeakDef(const CXXRecordDecl *D)
Definition Visitor.cpp:387
static bool hasRTTI(const CXXRecordDecl *D)
Definition Visitor.cpp:400
static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal=false)
Definition Visitor.cpp:67
static bool isExported(const NamedDecl *D)
Definition Visitor.cpp:36
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ Result
The result type of a method or function.
@ ExplicitInstantiation
We are parsing an explicit instantiation.
CXXDtorType
C++ destructor types.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
@ Type
The name was classified as a type.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
bool isExternallyVisible(Linkage L)
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
@ DefaultVisibility
Objects with "default" visibility are seen by the dynamic linker and act like normal objects.
Diagnostic wrappers for TextAPI types for error reporting.
Storage of availability attributes for a declaration.
static AvailabilityInfo createFromDecl(const Decl *Decl)
std::shared_ptr< FrontendRecordsSlice > Slice
Active TargetSlice for symbol record collection.
std::unique_ptr< DylibVerifier > Verifier
Verifier when binary dylib is passed as input.