16#include "llvm/ADT/StringRef.h"
17#include "llvm/IR/DataLayout.h"
18#include "llvm/IR/Mangler.h"
24enum class CXXLinkage {
37 auto LV =
D->getLinkageAndVisibility();
43 bool HasInlineAttribute =
false;
45 (!
D->getASTContext().getLangOpts().CPlusPlus &&
46 !
D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
47 !
D->hasAttr<DLLExportAttr>());
50 for (
const auto *RD :
D->redecls()) {
53 HasInlineAttribute =
true;
54 if (!(NoCXXAttr || RD->hasAttr<GNUInlineAttr>()))
56 if (RD->doesThisDeclarationHaveABody() &&
57 RD->isInlineDefinitionExternallyVisible())
61 if (!HasInlineAttribute)
70 Result |= SymbolFlags::WeakDefined;
72 Result |= SymbolFlags::ThreadLocalValue;
85std::string InstallAPIVisitor::getMangledName(
const NamedDecl *
D)
const {
87 if (MC->shouldMangleDeclName(
D)) {
88 raw_svector_ostream NStream(Name);
89 MC->mangleName(
D, NStream);
91 Name +=
D->getNameAsString();
93 return getBackendMangledName(Name);
96std::string InstallAPIVisitor::getBackendMangledName(Twine Name)
const {
98 Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
99 return std::string(FinalName);
102std::optional<HeaderType>
103InstallAPIVisitor::getAccessForDecl(
const NamedDecl *
D)
const {
104 SourceLocation
Loc =
D->getLocation();
120 if (!Header.has_value())
133 for (;
D !=
nullptr;
D =
D->getSuperClass())
134 if (
D->hasAttr<ObjCExceptionAttr>())
139void InstallAPIVisitor::recordObjCInstanceVariables(
141 const llvm::iterator_range<
148 Linkage = RecordLinkage::Unknown;
150 else if (ContainerLinkage != RecordLinkage::Unknown)
152 for (
const auto *IV : Ivars) {
153 auto Access = getAccessForDecl(IV);
156 StringRef Name = IV->getName();
158 auto AC = IV->getCanonicalAccessControl();
161 Ctx.
Verifier->verify(ObjCIVR, FA, SuperClass);
167 if (!
D->isThisDeclarationADefinition())
171 auto Access = getAccessForDecl(
D);
175 StringRef Name =
D->getObjCRuntimeNameAsString();
177 isExported(
D) ? RecordLinkage::Exported : RecordLinkage::Internal;
179 const bool IsEHType =
180 (!
D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
184 Ctx.
Slice->addObjCInterface(Name,
Linkage, Avail,
D, *Access, IsEHType);
188 StringRef SuperClassName;
189 if (
const auto *SuperClass =
D->getSuperClass())
190 SuperClassName = SuperClass->getObjCRuntimeNameAsString();
192 recordObjCInstanceVariables(
D->getASTContext(),
Class,
Class->getName(),
198 StringRef CategoryName =
D->getName();
200 auto Access = getAccessForDecl(
D);
205 const StringRef InterfaceName = InterfaceD->
getName();
208 Ctx.
Slice->addObjCCategory(InterfaceName, CategoryName, Avail,
D, *Access)
210 recordObjCInstanceVariables(
D->getASTContext(), CategoryRecord, InterfaceName,
217 if (isa<ParmVarDecl>(
D))
221 if (
D->getDeclContext()->isRecord())
225 if (!
D->isDefinedOutsideFunctionOrMethod())
229 if (
D->getASTContext().getTemplateOrSpecializationInfo(
D) &&
234 auto Access = getAccessForDecl(
D);
239 isExported(
D) ? RecordLinkage::Exported : RecordLinkage::Internal;
240 const bool WeakDef =
D->hasAttr<WeakAttr>();
243 auto [GR, FA] = Ctx.
Slice->addGlobal(getMangledName(
D),
Linkage,
244 GlobalRecord::Kind::Variable, Avail,
D,
245 *Access,
getFlags(WeakDef, ThreadLocal));
253 if (M->getParent()->getDescribedClassTemplate() !=
nullptr)
263 if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M))
268 switch (
D->getTemplatedKind()) {
274 if (
auto *TempInfo =
D->getTemplateSpecializationInfo()) {
275 if (!TempInfo->isExplicitInstantiationOrSpecialization())
284 auto Access = getAccessForDecl(
D);
287 auto Name = getMangledName(
D);
294 ? RecordLinkage::Internal
295 : RecordLinkage::Exported;
297 Ctx.
Slice->addGlobal(Name,
Linkage, GlobalRecord::Kind::Function, Avail,
306 if (!
D->hasDefinition() || !
D->isDynamicClass())
309 assert(
D->isExternallyVisible() &&
"Should be externally visible");
310 assert(
D->isCompleteDefinition() &&
"Only works on complete definitions");
313 D->getASTContext().getCurrentKeyFunction(
D);
325 "Unexpected TemplateSpecializationKind for key function");
327 }
else if (
D->isAbstract()) {
333 switch (
D->getTemplateSpecializationKind()) {
344 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
348 assert((
D->hasDefinition() &&
D->isDynamicClass()) &&
"Record has no vtable");
349 assert(
D->isExternallyVisible() &&
"Record should be externally visible");
351 return CXXLinkage::PrivateLinkage;
354 D->getASTContext().getCurrentKeyFunction(
D);
362 return CXXLinkage::LinkOnceODRLinkage;
363 return CXXLinkage::ExternalLinkage;
365 llvm_unreachable(
"No external vtable for implicit instantiations");
367 return CXXLinkage::WeakODRLinkage;
370 "Unexpected TemplateSpecializationKind for key function");
374 switch (
D->getTemplateSpecializationKind()) {
378 return CXXLinkage::LinkOnceODRLinkage;
381 return CXXLinkage::WeakODRLinkage;
384 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
388 if (
D->hasAttr<WeakAttr>())
391 if (
D->isAbstract() &&
D->getASTContext().getCurrentKeyFunction(
D) ==
nullptr)
394 if (
D->isDynamicClass())
401 if (!
D->getASTContext().getLangOpts().RTTI)
404 if (!
D->hasDefinition())
407 if (!
D->isDynamicClass())
424InstallAPIVisitor::getMangledCXXRTTIName(
const CXXRecordDecl *
D)
const {
426 raw_svector_ostream NameStream(Name);
427 MC->mangleCXXRTTIName(MC->getASTContext().getCanonicalTagType(
D), NameStream);
429 return getBackendMangledName(Name);
432std::string InstallAPIVisitor::getMangledCXXRTTI(
const CXXRecordDecl *
D)
const {
434 raw_svector_ostream NameStream(Name);
435 MC->mangleCXXRTTI(MC->getASTContext().getCanonicalTagType(
D), NameStream);
437 return getBackendMangledName(Name);
441InstallAPIVisitor::getMangledCXXVTableName(
const CXXRecordDecl *
D)
const {
443 raw_svector_ostream NameStream(Name);
444 MC->mangleCXXVTable(
D, NameStream);
446 return getBackendMangledName(Name);
449std::string InstallAPIVisitor::getMangledCXXThunk(
450 const GlobalDecl &
D,
const ThunkInfo &Thunk,
bool ElideOverrideInfo)
const {
452 raw_svector_ostream NameStream(Name);
453 const auto *
Method = cast<CXXMethodDecl>(
D.getDecl());
454 if (
const auto *Dtor = dyn_cast<CXXDestructorDecl>(
Method))
455 MC->mangleCXXDtorThunk(Dtor,
D.getDtorType(), Thunk, ElideOverrideInfo,
458 MC->mangleThunk(
Method, Thunk, ElideOverrideInfo, NameStream);
460 return getBackendMangledName(Name);
463std::string InstallAPIVisitor::getMangledCtorDtor(
const CXXMethodDecl *
D,
466 raw_svector_ostream NameStream(Name);
468 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(
D))
471 const auto *Dtor = cast<CXXDestructorDecl>(
D);
474 MC->mangleName(GD, NameStream);
475 return getBackendMangledName(Name);
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,
493 if (!
D->getDescribedClassTemplate() && !
D->isInvalidDecl()) {
494 VTableContextBase *VTable =
D->getASTContext().getVTableContext();
495 auto AddThunk = [&](GlobalDecl GD) {
497 VTable->getThunkInfo(GD);
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);
511 for (
const auto *
Method :
D->methods()) {
512 if (isa<CXXConstructorDecl>(
Method) || !
Method->isVirtual())
515 if (
auto Dtor = dyn_cast<CXXDestructorDecl>(
Method)) {
517 if (Dtor->isDefaulted())
532 std::string Name = getMangledCXXRTTI(
D);
534 Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
535 GlobalRecord::Kind::Variable, Avail,
D, Access);
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);
545 for (
const auto &It :
D->bases()) {
546 const CXXRecordDecl *
Base = cast<CXXRecordDecl>(
547 It.getType()->castAs<RecordType>()->getOriginalDecl());
548 const auto BaseAccess = getAccessForDecl(
Base);
552 emitVTableSymbols(
Base, BaseAvail, *BaseAccess,
true);
557 if (!
D->isCompleteDefinition())
561 if (
D->getDescribedClassTemplate() !=
nullptr)
565 if (isa<ClassTemplatePartialSpecializationDecl>(
D))
568 auto Access = getAccessForDecl(
D);
575 emitVTableSymbols(
D, Avail, *Access);
578 bool KeepInlineAsWeak =
false;
579 if (
auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(
D)) {
580 ClassSK = Templ->getTemplateSpecializationKind();
582 KeepInlineAsWeak =
true;
586 for (
const auto *M :
D->methods()) {
589 bool WeakDef =
false;
591 if (!KeepInlineAsWeak)
600 switch (M->getTemplateSpecializationKind()) {
615 if (!M->isUserProvided())
622 const auto Access = getAccessForDecl(M);
627 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(M)) {
629 if (Ctor->isDefaulted())
632 std::string Name = getMangledCtorDtor(M,
Ctor_Base);
633 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
634 GlobalRecord::Kind::Function, Avail,
638 if (!
D->isAbstract()) {
640 auto [GR, FA] = Ctx.
Slice->addGlobal(
641 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
649 if (
const auto *Dtor = dyn_cast<CXXDestructorDecl>(M)) {
651 if (Dtor->isDefaulted())
654 std::string Name = getMangledCtorDtor(M,
Dtor_Base);
655 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
656 GlobalRecord::Kind::Function, Avail,
661 auto [CompleteGR, CompleteFA] = Ctx.
Slice->addGlobal(
662 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
D,
664 Ctx.
Verifier->verify(CompleteGR, CompleteFA);
666 if (Dtor->isVirtual()) {
668 auto [VirtualGR, VirtualFA] = Ctx.
Slice->addGlobal(
669 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
671 Ctx.
Verifier->verify(VirtualGR, VirtualFA);
680 if (M->isPureVirtual())
683 std::string Name = getMangledName(M);
684 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
685 GlobalRecord::Kind::Function, Avail, M,
690 if (
auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(
D)) {
691 if (!Templ->isExplicitInstantiationOrSpecialization())
696 using var_range = iterator_range<var_iter>;
697 for (
const auto *Var : var_range(
D->decls())) {
704 if (Var->isStaticDataMember() && Var->hasInit())
711 const std::string Name = getMangledName(Var);
712 const auto Access = getAccessForDecl(Var);
716 const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak;
718 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
719 GlobalRecord::Kind::Variable, Avail,
D,
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
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
bool hasErrorOccurred() const
A dynamically typed AST node container.
Represents a function declaration or definition.
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
@ TK_DependentFunctionTemplateSpecialization
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
clang::ObjCRuntime ObjCRuntime
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
ObjCCategoryDecl - Represents a category declaration.
Represents an ObjC class declaration.
bool isFragile() const
The inverse of isNonFragile(): does this runtime follow the set of implied behaviors for a "fragile" ...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
Represents a variable declaration or definition.
@ TLS_None
Not a TLS variable.
void HandleTranslationUnit(ASTContext &ASTCtx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
bool VisitCXXRecordDecl(const CXXRecordDecl *D)
Collect global c++ declarations.
bool VisitFunctionDecl(const FunctionDecl *D)
Collect global functions.
bool VisitVarDecl(const VarDecl *D)
Collect global variables.
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D)
Collect Objective-C Category/Extension declarations.
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D)
Collect Objective-C Interface declarations.
Defines the Linkage enumeration and various utility functions.
The DirectoryScanner for collecting library files on the file system.
static bool isInlined(const FunctionDecl *D)
static CXXLinkage getVTableLinkage(const CXXRecordDecl *D)
@ 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.
static bool hasVTable(const CXXRecordDecl *D)
static bool isRTTIWeakDef(const CXXRecordDecl *D)
static bool hasRTTI(const CXXRecordDecl *D)
static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal=false)
static bool isExported(const NamedDecl *D)
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
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.
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,...
@ 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::optional< HeaderType > findAndRecordFile(const FileEntry *FE, const Preprocessor &PP)
Record visited files during frontend actions to determine whether to include their declarations for T...
std::shared_ptr< FrontendRecordsSlice > Slice
Active TargetSlice for symbol record collection.
std::unique_ptr< DylibVerifier > Verifier
Verifier when binary dylib is passed as input.