16#include "llvm/ADT/SmallString.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/IR/DataLayout.h"
19#include "llvm/IR/Mangler.h"
25enum class CXXLinkage {
38 auto LV =
D->getLinkageAndVisibility();
44 bool HasInlineAttribute =
false;
46 (!
D->getASTContext().getLangOpts().CPlusPlus &&
47 !
D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
48 !
D->hasAttr<DLLExportAttr>());
51 for (
const auto *RD :
D->redecls()) {
54 HasInlineAttribute =
true;
55 if (!(NoCXXAttr || RD->hasAttr<GNUInlineAttr>()))
57 if (RD->doesThisDeclarationHaveABody() &&
58 RD->isInlineDefinitionExternallyVisible())
62 if (!HasInlineAttribute)
71 Result |= SymbolFlags::WeakDefined;
73 Result |= SymbolFlags::ThreadLocalValue;
86std::string InstallAPIVisitor::getMangledName(
const NamedDecl *
D)
const {
88 if (MC->shouldMangleDeclName(
D)) {
89 raw_svector_ostream NStream(Name);
90 MC->mangleName(
D, NStream);
92 Name +=
D->getNameAsString();
94 return getBackendMangledName(Name);
97std::string InstallAPIVisitor::getBackendMangledName(Twine Name)
const {
99 Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
100 return std::string(FinalName);
103std::optional<HeaderType>
104InstallAPIVisitor::getAccessForDecl(
const NamedDecl *
D)
const {
105 SourceLocation
Loc =
D->getLocation();
121 if (!Header.has_value())
134 for (;
D !=
nullptr;
D =
D->getSuperClass())
135 if (
D->hasAttr<ObjCExceptionAttr>())
140void InstallAPIVisitor::recordObjCInstanceVariables(
142 const llvm::iterator_range<
149 Linkage = RecordLinkage::Unknown;
151 else if (ContainerLinkage != RecordLinkage::Unknown)
153 for (
const auto *IV : Ivars) {
154 auto Access = getAccessForDecl(IV);
157 StringRef Name = IV->getName();
159 auto AC = IV->getCanonicalAccessControl();
162 Ctx.
Verifier->verify(ObjCIVR, FA, SuperClass);
168 if (!
D->isThisDeclarationADefinition())
172 auto Access = getAccessForDecl(
D);
176 StringRef Name =
D->getObjCRuntimeNameAsString();
178 isExported(
D) ? RecordLinkage::Exported : RecordLinkage::Internal;
180 const bool IsEHType =
181 (!
D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
185 Ctx.
Slice->addObjCInterface(Name,
Linkage, Avail,
D, *Access, IsEHType);
189 StringRef SuperClassName;
190 if (
const auto *SuperClass =
D->getSuperClass())
191 SuperClassName = SuperClass->getObjCRuntimeNameAsString();
193 recordObjCInstanceVariables(
D->getASTContext(),
Class,
Class->getName(),
199 StringRef CategoryName =
D->getName();
201 auto Access = getAccessForDecl(
D);
206 const StringRef InterfaceName = InterfaceD->
getName();
209 Ctx.
Slice->addObjCCategory(InterfaceName, CategoryName, Avail,
D, *Access)
211 recordObjCInstanceVariables(
D->getASTContext(), CategoryRecord, InterfaceName,
218 if (isa<ParmVarDecl>(
D))
222 if (
D->getDeclContext()->isRecord())
226 if (!
D->isDefinedOutsideFunctionOrMethod())
230 if (
D->getASTContext().getTemplateOrSpecializationInfo(
D) &&
235 auto Access = getAccessForDecl(
D);
240 isExported(
D) ? RecordLinkage::Exported : RecordLinkage::Internal;
241 const bool WeakDef =
D->hasAttr<WeakAttr>();
244 auto [GR, FA] = Ctx.
Slice->addGlobal(getMangledName(
D),
Linkage,
245 GlobalRecord::Kind::Variable, Avail,
D,
246 *Access,
getFlags(WeakDef, ThreadLocal));
254 if (M->getParent()->getDescribedClassTemplate() !=
nullptr)
264 if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M))
269 switch (
D->getTemplatedKind()) {
275 if (
auto *TempInfo =
D->getTemplateSpecializationInfo()) {
276 if (!TempInfo->isExplicitInstantiationOrSpecialization())
285 auto Access = getAccessForDecl(
D);
288 auto Name = getMangledName(
D);
290 const bool ExplicitInstantiation =
D->getTemplateSpecializationKind() ==
292 const bool WeakDef = ExplicitInstantiation ||
D->hasAttr<WeakAttr>();
295 ? RecordLinkage::Internal
296 : RecordLinkage::Exported;
298 Ctx.
Slice->addGlobal(Name,
Linkage, GlobalRecord::Kind::Function, Avail,
307 if (!
D->hasDefinition() || !
D->isDynamicClass())
310 assert(
D->isExternallyVisible() &&
"Should be externally visible");
311 assert(
D->isCompleteDefinition() &&
"Only works on complete definitions");
314 D->getASTContext().getCurrentKeyFunction(
D);
326 "Unexpected TemplateSpecializationKind for key function");
328 }
else if (
D->isAbstract()) {
334 switch (
D->getTemplateSpecializationKind()) {
345 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
349 assert((
D->hasDefinition() &&
D->isDynamicClass()) &&
"Record has no vtable");
350 assert(
D->isExternallyVisible() &&
"Record should be externally visible");
352 return CXXLinkage::PrivateLinkage;
355 D->getASTContext().getCurrentKeyFunction(
D);
363 return CXXLinkage::LinkOnceODRLinkage;
364 return CXXLinkage::ExternalLinkage;
366 llvm_unreachable(
"No external vtable for implicit instantiations");
368 return CXXLinkage::WeakODRLinkage;
371 "Unexpected TemplateSpecializationKind for key function");
375 switch (
D->getTemplateSpecializationKind()) {
379 return CXXLinkage::LinkOnceODRLinkage;
382 return CXXLinkage::WeakODRLinkage;
385 llvm_unreachable(
"Invalid TemplateSpecializationKind!");
389 if (
D->hasAttr<WeakAttr>())
392 if (
D->isAbstract() &&
D->getASTContext().getCurrentKeyFunction(
D) ==
nullptr)
395 if (
D->isDynamicClass())
402 if (!
D->getASTContext().getLangOpts().RTTI)
405 if (!
D->hasDefinition())
408 if (!
D->isDynamicClass())
425InstallAPIVisitor::getMangledCXXRTTIName(
const CXXRecordDecl *
D)
const {
427 raw_svector_ostream NameStream(Name);
428 MC->mangleCXXRTTIName(
QualType(
D->getTypeForDecl(), 0), NameStream);
430 return getBackendMangledName(Name);
433std::string InstallAPIVisitor::getMangledCXXRTTI(
const CXXRecordDecl *
D)
const {
435 raw_svector_ostream NameStream(Name);
436 MC->mangleCXXRTTI(QualType(
D->getTypeForDecl(), 0), NameStream);
438 return getBackendMangledName(Name);
442InstallAPIVisitor::getMangledCXXVTableName(
const CXXRecordDecl *
D)
const {
444 raw_svector_ostream NameStream(Name);
445 MC->mangleCXXVTable(
D, NameStream);
447 return getBackendMangledName(Name);
450std::string InstallAPIVisitor::getMangledCXXThunk(
451 const GlobalDecl &
D,
const ThunkInfo &Thunk,
bool ElideOverrideInfo)
const {
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,
459 MC->mangleThunk(Method, Thunk, ElideOverrideInfo, NameStream);
461 return getBackendMangledName(Name);
464std::string InstallAPIVisitor::getMangledCtorDtor(
const CXXMethodDecl *
D,
467 raw_svector_ostream NameStream(Name);
469 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(
D))
472 const auto *Dtor = cast<CXXDestructorDecl>(
D);
475 MC->mangleName(GD, NameStream);
476 return getBackendMangledName(Name);
479void InstallAPIVisitor::emitVTableSymbols(
const CXXRecordDecl *
D,
480 const AvailabilityInfo &Avail,
482 bool EmittedVTable) {
484 EmittedVTable =
true;
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,
494 if (!
D->getDescribedClassTemplate() && !
D->isInvalidDecl()) {
495 VTableContextBase *VTable =
D->getASTContext().getVTableContext();
496 auto AddThunk = [&](GlobalDecl GD) {
498 VTable->getThunkInfo(GD);
502 for (
const auto &Thunk : *Thunks) {
503 const std::string Name =
504 getMangledCXXThunk(GD, Thunk,
true);
505 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
506 GlobalRecord::Kind::Function,
507 Avail, GD.getDecl(), Access);
512 for (
const auto *Method :
D->methods()) {
513 if (isa<CXXConstructorDecl>(Method) || !Method->isVirtual())
516 if (
auto Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
518 if (Dtor->isDefaulted())
533 std::string Name = getMangledCXXRTTI(
D);
535 Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
536 GlobalRecord::Kind::Variable, Avail,
D, Access);
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);
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);
553 emitVTableSymbols(
Base, BaseAvail, *BaseAccess,
true);
558 if (!
D->isCompleteDefinition())
562 if (
D->getDescribedClassTemplate() !=
nullptr)
566 if (isa<ClassTemplatePartialSpecializationDecl>(
D))
569 auto Access = getAccessForDecl(
D);
576 emitVTableSymbols(
D, Avail, *Access);
579 bool KeepInlineAsWeak =
false;
580 if (
auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(
D)) {
581 ClassSK = Templ->getTemplateSpecializationKind();
583 KeepInlineAsWeak =
true;
587 for (
const auto *M :
D->methods()) {
590 bool WeakDef =
false;
592 if (!KeepInlineAsWeak)
601 switch (M->getTemplateSpecializationKind()) {
616 if (!M->isUserProvided())
623 const auto Access = getAccessForDecl(M);
628 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(M)) {
630 if (Ctor->isDefaulted())
633 std::string Name = getMangledCtorDtor(M,
Ctor_Base);
634 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
635 GlobalRecord::Kind::Function, Avail,
639 if (!
D->isAbstract()) {
641 auto [GR, FA] = Ctx.
Slice->addGlobal(
642 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
650 if (
const auto *Dtor = dyn_cast<CXXDestructorDecl>(M)) {
652 if (Dtor->isDefaulted())
655 std::string Name = getMangledCtorDtor(M,
Dtor_Base);
656 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
657 GlobalRecord::Kind::Function, Avail,
662 auto [CompleteGR, CompleteFA] = Ctx.
Slice->addGlobal(
663 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
D,
665 Ctx.
Verifier->verify(CompleteGR, CompleteFA);
667 if (Dtor->isVirtual()) {
669 auto [VirtualGR, VirtualFA] = Ctx.
Slice->addGlobal(
670 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
672 Ctx.
Verifier->verify(VirtualGR, VirtualFA);
681 if (M->isPureVirtual())
684 std::string Name = getMangledName(M);
685 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
686 GlobalRecord::Kind::Function, Avail, M,
691 if (
auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(
D)) {
692 if (!Templ->isExplicitInstantiationOrSpecialization())
697 using var_range = iterator_range<var_iter>;
698 for (
const auto *Var : var_range(
D->decls())) {
705 if (Var->isStaticDataMember() && Var->hasInit())
712 const std::string Name = getMangledName(Var);
713 const auto Access = getAccessForDecl(Var);
717 const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak;
719 auto [GR, FA] = Ctx.
Slice->addGlobal(Name, RecordLinkage::Exported,
720 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" ...
A (possibly-)qualified type.
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.
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.