1c6cbf81cSCyndy Ishida //===- Visitor.cpp ---------------------------------------------*- C++ -*-===//
2c6cbf81cSCyndy Ishida //
3c6cbf81cSCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c6cbf81cSCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
5c6cbf81cSCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c6cbf81cSCyndy Ishida //
7c6cbf81cSCyndy Ishida //===----------------------------------------------------------------------===//
8c6cbf81cSCyndy Ishida
9c6cbf81cSCyndy Ishida #include "clang/InstallAPI/Visitor.h"
102c93beccSCyndy Ishida #include "clang/AST/Availability.h"
1150ae8a2aSCyndy Ishida #include "clang/AST/ParentMapContext.h"
122c93beccSCyndy Ishida #include "clang/AST/VTableBuilder.h"
13c6cbf81cSCyndy Ishida #include "clang/Basic/Linkage.h"
14f2794cceSCyndy Ishida #include "clang/InstallAPI/DylibVerifier.h"
15a38b7a43SCyndy Ishida #include "clang/InstallAPI/FrontendRecords.h"
16c6cbf81cSCyndy Ishida #include "llvm/ADT/SmallString.h"
17c6cbf81cSCyndy Ishida #include "llvm/ADT/StringRef.h"
18c6cbf81cSCyndy Ishida #include "llvm/IR/DataLayout.h"
19c6cbf81cSCyndy Ishida #include "llvm/IR/Mangler.h"
20c6cbf81cSCyndy Ishida
21c6cbf81cSCyndy Ishida using namespace llvm;
22c6cbf81cSCyndy Ishida using namespace llvm::MachO;
23c6cbf81cSCyndy Ishida
242c93beccSCyndy Ishida namespace {
252c93beccSCyndy Ishida enum class CXXLinkage {
262c93beccSCyndy Ishida ExternalLinkage,
272c93beccSCyndy Ishida LinkOnceODRLinkage,
282c93beccSCyndy Ishida WeakODRLinkage,
292c93beccSCyndy Ishida PrivateLinkage,
302c93beccSCyndy Ishida };
312c93beccSCyndy Ishida }
322c93beccSCyndy Ishida
33c6cbf81cSCyndy Ishida namespace clang::installapi {
34c6cbf81cSCyndy Ishida
3514faf0d4SCyndy Ishida // Exported NamedDecl needs to have external linkage and
36c6cbf81cSCyndy Ishida // default visibility from LinkageComputer.
isExported(const NamedDecl * D)37c6cbf81cSCyndy Ishida static bool isExported(const NamedDecl *D) {
38c6cbf81cSCyndy Ishida auto LV = D->getLinkageAndVisibility();
39c6cbf81cSCyndy Ishida return isExternallyVisible(LV.getLinkage()) &&
40c6cbf81cSCyndy Ishida (LV.getVisibility() == DefaultVisibility);
41c6cbf81cSCyndy Ishida }
42c6cbf81cSCyndy Ishida
isInlined(const FunctionDecl * D)4350ae8a2aSCyndy Ishida static bool isInlined(const FunctionDecl *D) {
4450ae8a2aSCyndy Ishida bool HasInlineAttribute = false;
4550ae8a2aSCyndy Ishida bool NoCXXAttr =
4650ae8a2aSCyndy Ishida (!D->getASTContext().getLangOpts().CPlusPlus &&
4750ae8a2aSCyndy Ishida !D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
4850ae8a2aSCyndy Ishida !D->hasAttr<DLLExportAttr>());
4950ae8a2aSCyndy Ishida
5050ae8a2aSCyndy Ishida // Check all redeclarations to find an inline attribute or keyword.
5150ae8a2aSCyndy Ishida for (const auto *RD : D->redecls()) {
5250ae8a2aSCyndy Ishida if (!RD->isInlined())
5350ae8a2aSCyndy Ishida continue;
5450ae8a2aSCyndy Ishida HasInlineAttribute = true;
5550ae8a2aSCyndy Ishida if (!(NoCXXAttr || RD->hasAttr<GNUInlineAttr>()))
5650ae8a2aSCyndy Ishida continue;
5750ae8a2aSCyndy Ishida if (RD->doesThisDeclarationHaveABody() &&
5850ae8a2aSCyndy Ishida RD->isInlineDefinitionExternallyVisible())
5950ae8a2aSCyndy Ishida return false;
6050ae8a2aSCyndy Ishida }
6150ae8a2aSCyndy Ishida
6250ae8a2aSCyndy Ishida if (!HasInlineAttribute)
6350ae8a2aSCyndy Ishida return false;
6450ae8a2aSCyndy Ishida
6550ae8a2aSCyndy Ishida return true;
6650ae8a2aSCyndy Ishida }
6750ae8a2aSCyndy Ishida
getFlags(bool WeakDef,bool ThreadLocal=false)682c93beccSCyndy Ishida static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal = false) {
69c6cbf81cSCyndy Ishida SymbolFlags Result = SymbolFlags::None;
70c6cbf81cSCyndy Ishida if (WeakDef)
71c6cbf81cSCyndy Ishida Result |= SymbolFlags::WeakDefined;
72c6cbf81cSCyndy Ishida if (ThreadLocal)
73c6cbf81cSCyndy Ishida Result |= SymbolFlags::ThreadLocalValue;
74c6cbf81cSCyndy Ishida
75c6cbf81cSCyndy Ishida return Result;
76c6cbf81cSCyndy Ishida }
77c6cbf81cSCyndy Ishida
HandleTranslationUnit(ASTContext & ASTCtx)78c6cbf81cSCyndy Ishida void InstallAPIVisitor::HandleTranslationUnit(ASTContext &ASTCtx) {
79c6cbf81cSCyndy Ishida if (ASTCtx.getDiagnostics().hasErrorOccurred())
80c6cbf81cSCyndy Ishida return;
81c6cbf81cSCyndy Ishida
82c6cbf81cSCyndy Ishida auto *D = ASTCtx.getTranslationUnitDecl();
83c6cbf81cSCyndy Ishida TraverseDecl(D);
84c6cbf81cSCyndy Ishida }
85c6cbf81cSCyndy Ishida
getMangledName(const NamedDecl * D) const86c6cbf81cSCyndy Ishida std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
87c6cbf81cSCyndy Ishida SmallString<256> Name;
88c6cbf81cSCyndy Ishida if (MC->shouldMangleDeclName(D)) {
89c6cbf81cSCyndy Ishida raw_svector_ostream NStream(Name);
90c6cbf81cSCyndy Ishida MC->mangleName(D, NStream);
91c6cbf81cSCyndy Ishida } else
92c6cbf81cSCyndy Ishida Name += D->getNameAsString();
93c6cbf81cSCyndy Ishida
94c6cbf81cSCyndy Ishida return getBackendMangledName(Name);
95c6cbf81cSCyndy Ishida }
96c6cbf81cSCyndy Ishida
getBackendMangledName(Twine Name) const97c6cbf81cSCyndy Ishida std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
98c6cbf81cSCyndy Ishida SmallString<256> FinalName;
99c6cbf81cSCyndy Ishida Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
100c6cbf81cSCyndy Ishida return std::string(FinalName);
101c6cbf81cSCyndy Ishida }
102c6cbf81cSCyndy Ishida
10317ede03aSCyndy Ishida std::optional<HeaderType>
getAccessForDecl(const NamedDecl * D) const10417ede03aSCyndy Ishida InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {
10517ede03aSCyndy Ishida SourceLocation Loc = D->getLocation();
10617ede03aSCyndy Ishida if (Loc.isInvalid())
10717ede03aSCyndy Ishida return std::nullopt;
10817ede03aSCyndy Ishida
10917ede03aSCyndy Ishida // If the loc refers to a macro expansion, InstallAPI needs to first get the
11017ede03aSCyndy Ishida // file location of the expansion.
11117ede03aSCyndy Ishida auto FileLoc = SrcMgr.getFileLoc(Loc);
11217ede03aSCyndy Ishida FileID ID = SrcMgr.getFileID(FileLoc);
11317ede03aSCyndy Ishida if (ID.isInvalid())
11417ede03aSCyndy Ishida return std::nullopt;
11517ede03aSCyndy Ishida
11617ede03aSCyndy Ishida const FileEntry *FE = SrcMgr.getFileEntryForID(ID);
11717ede03aSCyndy Ishida if (!FE)
11817ede03aSCyndy Ishida return std::nullopt;
11917ede03aSCyndy Ishida
12017ede03aSCyndy Ishida auto Header = Ctx.findAndRecordFile(FE, PP);
12117ede03aSCyndy Ishida if (!Header.has_value())
12217ede03aSCyndy Ishida return std::nullopt;
12317ede03aSCyndy Ishida
12417ede03aSCyndy Ishida HeaderType Access = Header.value();
12517ede03aSCyndy Ishida assert(Access != HeaderType::Unknown && "unexpected access level for global");
12617ede03aSCyndy Ishida return Access;
12717ede03aSCyndy Ishida }
12817ede03aSCyndy Ishida
12917ede03aSCyndy Ishida /// Check if the interface itself or any of its super classes have an
13017ede03aSCyndy Ishida /// exception attribute. InstallAPI needs to export an additional symbol
13117ede03aSCyndy Ishida /// ("OBJC_EHTYPE_$CLASS_NAME") if any of the classes have the exception
13217ede03aSCyndy Ishida /// attribute.
hasObjCExceptionAttribute(const ObjCInterfaceDecl * D)13317ede03aSCyndy Ishida static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D) {
13417ede03aSCyndy Ishida for (; D != nullptr; D = D->getSuperClass())
13517ede03aSCyndy Ishida if (D->hasAttr<ObjCExceptionAttr>())
13617ede03aSCyndy Ishida return true;
13717ede03aSCyndy Ishida
13817ede03aSCyndy Ishida return false;
13917ede03aSCyndy Ishida }
recordObjCInstanceVariables(const ASTContext & ASTCtx,ObjCContainerRecord * Record,StringRef SuperClass,const llvm::iterator_range<DeclContext::specific_decl_iterator<ObjCIvarDecl>> Ivars)14010ccde30SCyndy Ishida void InstallAPIVisitor::recordObjCInstanceVariables(
14110ccde30SCyndy Ishida const ASTContext &ASTCtx, ObjCContainerRecord *Record, StringRef SuperClass,
14210ccde30SCyndy Ishida const llvm::iterator_range<
14310ccde30SCyndy Ishida DeclContext::specific_decl_iterator<ObjCIvarDecl>>
14410ccde30SCyndy Ishida Ivars) {
14510ccde30SCyndy Ishida RecordLinkage Linkage = RecordLinkage::Exported;
14610ccde30SCyndy Ishida const RecordLinkage ContainerLinkage = Record->getLinkage();
14710ccde30SCyndy Ishida // If fragile, set to unknown.
14810ccde30SCyndy Ishida if (ASTCtx.getLangOpts().ObjCRuntime.isFragile())
14910ccde30SCyndy Ishida Linkage = RecordLinkage::Unknown;
15010ccde30SCyndy Ishida // Linkage should be inherited from container.
15110ccde30SCyndy Ishida else if (ContainerLinkage != RecordLinkage::Unknown)
15210ccde30SCyndy Ishida Linkage = ContainerLinkage;
15310ccde30SCyndy Ishida for (const auto *IV : Ivars) {
15410ccde30SCyndy Ishida auto Access = getAccessForDecl(IV);
15510ccde30SCyndy Ishida if (!Access)
15610ccde30SCyndy Ishida continue;
15710ccde30SCyndy Ishida StringRef Name = IV->getName();
15810ccde30SCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(IV);
15910ccde30SCyndy Ishida auto AC = IV->getCanonicalAccessControl();
160f2794cceSCyndy Ishida auto [ObjCIVR, FA] =
16110ccde30SCyndy Ishida Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC);
162f2794cceSCyndy Ishida Ctx.Verifier->verify(ObjCIVR, FA, SuperClass);
16310ccde30SCyndy Ishida }
16410ccde30SCyndy Ishida }
16517ede03aSCyndy Ishida
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)16617ede03aSCyndy Ishida bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
16717ede03aSCyndy Ishida // Skip forward declaration for classes (@class)
16817ede03aSCyndy Ishida if (!D->isThisDeclarationADefinition())
16917ede03aSCyndy Ishida return true;
17017ede03aSCyndy Ishida
17117ede03aSCyndy Ishida // Skip over declarations that access could not be collected for.
17217ede03aSCyndy Ishida auto Access = getAccessForDecl(D);
17317ede03aSCyndy Ishida if (!Access)
17417ede03aSCyndy Ishida return true;
17517ede03aSCyndy Ishida
17617ede03aSCyndy Ishida StringRef Name = D->getObjCRuntimeNameAsString();
17717ede03aSCyndy Ishida const RecordLinkage Linkage =
17817ede03aSCyndy Ishida isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
17917ede03aSCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
18017ede03aSCyndy Ishida const bool IsEHType =
18117ede03aSCyndy Ishida (!D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
18217ede03aSCyndy Ishida hasObjCExceptionAttribute(D));
18317ede03aSCyndy Ishida
184f2794cceSCyndy Ishida auto [Class, FA] =
18517ede03aSCyndy Ishida Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
186f2794cceSCyndy Ishida Ctx.Verifier->verify(Class, FA);
18710ccde30SCyndy Ishida
18810ccde30SCyndy Ishida // Get base class.
18910ccde30SCyndy Ishida StringRef SuperClassName;
19010ccde30SCyndy Ishida if (const auto *SuperClass = D->getSuperClass())
19110ccde30SCyndy Ishida SuperClassName = SuperClass->getObjCRuntimeNameAsString();
19210ccde30SCyndy Ishida
193f2794cceSCyndy Ishida recordObjCInstanceVariables(D->getASTContext(), Class, Class->getName(),
19410ccde30SCyndy Ishida D->ivars());
19510ccde30SCyndy Ishida return true;
19610ccde30SCyndy Ishida }
19710ccde30SCyndy Ishida
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)19810ccde30SCyndy Ishida bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
19910ccde30SCyndy Ishida StringRef CategoryName = D->getName();
20010ccde30SCyndy Ishida // Skip over declarations that access could not be collected for.
20110ccde30SCyndy Ishida auto Access = getAccessForDecl(D);
20210ccde30SCyndy Ishida if (!Access)
20310ccde30SCyndy Ishida return true;
20410ccde30SCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
20510ccde30SCyndy Ishida const ObjCInterfaceDecl *InterfaceD = D->getClassInterface();
20610ccde30SCyndy Ishida const StringRef InterfaceName = InterfaceD->getName();
20710ccde30SCyndy Ishida
208207f1531SCyndy Ishida ObjCCategoryRecord *CategoryRecord =
209207f1531SCyndy Ishida Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access)
210207f1531SCyndy Ishida .first;
211207f1531SCyndy Ishida recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName,
21210ccde30SCyndy Ishida D->ivars());
21317ede03aSCyndy Ishida return true;
21417ede03aSCyndy Ishida }
21517ede03aSCyndy Ishida
VisitVarDecl(const VarDecl * D)216c6cbf81cSCyndy Ishida bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
217c6cbf81cSCyndy Ishida // Skip function parameters.
218c6cbf81cSCyndy Ishida if (isa<ParmVarDecl>(D))
219c6cbf81cSCyndy Ishida return true;
220c6cbf81cSCyndy Ishida
221d4a01549SJay Foad // Skip variables in records. They are handled separately for C++.
222c6cbf81cSCyndy Ishida if (D->getDeclContext()->isRecord())
223c6cbf81cSCyndy Ishida return true;
224c6cbf81cSCyndy Ishida
225c6cbf81cSCyndy Ishida // Skip anything inside functions or methods.
226c6cbf81cSCyndy Ishida if (!D->isDefinedOutsideFunctionOrMethod())
227c6cbf81cSCyndy Ishida return true;
228c6cbf81cSCyndy Ishida
229c6cbf81cSCyndy Ishida // If this is a template but not specialization or instantiation, skip.
230c6cbf81cSCyndy Ishida if (D->getASTContext().getTemplateOrSpecializationInfo(D) &&
231c6cbf81cSCyndy Ishida D->getTemplateSpecializationKind() == TSK_Undeclared)
232c6cbf81cSCyndy Ishida return true;
233c6cbf81cSCyndy Ishida
23417ede03aSCyndy Ishida // Skip over declarations that access could not collected for.
23517ede03aSCyndy Ishida auto Access = getAccessForDecl(D);
23617ede03aSCyndy Ishida if (!Access)
23717ede03aSCyndy Ishida return true;
23817ede03aSCyndy Ishida
239c6cbf81cSCyndy Ishida const RecordLinkage Linkage =
240c6cbf81cSCyndy Ishida isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
241c6cbf81cSCyndy Ishida const bool WeakDef = D->hasAttr<WeakAttr>();
242c6cbf81cSCyndy Ishida const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None;
24317ede03aSCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
244f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(getMangledName(D), Linkage,
245f2794cceSCyndy Ishida GlobalRecord::Kind::Variable, Avail, D,
246f2794cceSCyndy Ishida *Access, getFlags(WeakDef, ThreadLocal));
247f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
248c6cbf81cSCyndy Ishida return true;
249c6cbf81cSCyndy Ishida }
250c6cbf81cSCyndy Ishida
VisitFunctionDecl(const FunctionDecl * D)25150ae8a2aSCyndy Ishida bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) {
25250ae8a2aSCyndy Ishida if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(D)) {
25350ae8a2aSCyndy Ishida // Skip member function in class templates.
25450ae8a2aSCyndy Ishida if (M->getParent()->getDescribedClassTemplate() != nullptr)
25550ae8a2aSCyndy Ishida return true;
25650ae8a2aSCyndy Ishida
25750ae8a2aSCyndy Ishida // Skip methods in CXX RecordDecls.
2585da39372Ssmanna12 for (const DynTypedNode &P : D->getASTContext().getParents(*M)) {
25950ae8a2aSCyndy Ishida if (P.get<CXXRecordDecl>())
26050ae8a2aSCyndy Ishida return true;
26150ae8a2aSCyndy Ishida }
26250ae8a2aSCyndy Ishida
26350ae8a2aSCyndy Ishida // Skip CXX ConstructorDecls and DestructorDecls.
26450ae8a2aSCyndy Ishida if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M))
26550ae8a2aSCyndy Ishida return true;
26650ae8a2aSCyndy Ishida }
26750ae8a2aSCyndy Ishida
26850ae8a2aSCyndy Ishida // Skip templated functions.
26950ae8a2aSCyndy Ishida switch (D->getTemplatedKind()) {
27050ae8a2aSCyndy Ishida case FunctionDecl::TK_NonTemplate:
27150ae8a2aSCyndy Ishida case FunctionDecl::TK_DependentNonTemplate:
27250ae8a2aSCyndy Ishida break;
27350ae8a2aSCyndy Ishida case FunctionDecl::TK_MemberSpecialization:
27450ae8a2aSCyndy Ishida case FunctionDecl::TK_FunctionTemplateSpecialization:
27550ae8a2aSCyndy Ishida if (auto *TempInfo = D->getTemplateSpecializationInfo()) {
27650ae8a2aSCyndy Ishida if (!TempInfo->isExplicitInstantiationOrSpecialization())
27750ae8a2aSCyndy Ishida return true;
27850ae8a2aSCyndy Ishida }
27950ae8a2aSCyndy Ishida break;
28050ae8a2aSCyndy Ishida case FunctionDecl::TK_FunctionTemplate:
28150ae8a2aSCyndy Ishida case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
28250ae8a2aSCyndy Ishida return true;
28350ae8a2aSCyndy Ishida }
28450ae8a2aSCyndy Ishida
28550ae8a2aSCyndy Ishida auto Access = getAccessForDecl(D);
28650ae8a2aSCyndy Ishida if (!Access)
28750ae8a2aSCyndy Ishida return true;
28850ae8a2aSCyndy Ishida auto Name = getMangledName(D);
28950ae8a2aSCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
29050ae8a2aSCyndy Ishida const bool ExplicitInstantiation = D->getTemplateSpecializationKind() ==
29150ae8a2aSCyndy Ishida TSK_ExplicitInstantiationDeclaration;
29250ae8a2aSCyndy Ishida const bool WeakDef = ExplicitInstantiation || D->hasAttr<WeakAttr>();
29350ae8a2aSCyndy Ishida const bool Inlined = isInlined(D);
29450ae8a2aSCyndy Ishida const RecordLinkage Linkage = (Inlined || !isExported(D))
29550ae8a2aSCyndy Ishida ? RecordLinkage::Internal
29650ae8a2aSCyndy Ishida : RecordLinkage::Exported;
297f2794cceSCyndy Ishida auto [GR, FA] =
298f2794cceSCyndy Ishida Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail,
299f2794cceSCyndy Ishida D, *Access, getFlags(WeakDef), Inlined);
300f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
3012c93beccSCyndy Ishida return true;
3022c93beccSCyndy Ishida }
3032c93beccSCyndy Ishida
hasVTable(const CXXRecordDecl * D)3042c93beccSCyndy Ishida static bool hasVTable(const CXXRecordDecl *D) {
3052c93beccSCyndy Ishida // Check if vtable symbols should be emitted, only dynamic classes need
3062c93beccSCyndy Ishida // vtables.
3072c93beccSCyndy Ishida if (!D->hasDefinition() || !D->isDynamicClass())
3082c93beccSCyndy Ishida return false;
3092c93beccSCyndy Ishida
3102c93beccSCyndy Ishida assert(D->isExternallyVisible() && "Should be externally visible");
3112c93beccSCyndy Ishida assert(D->isCompleteDefinition() && "Only works on complete definitions");
3122c93beccSCyndy Ishida
3132c93beccSCyndy Ishida const CXXMethodDecl *KeyFunctionD =
3142c93beccSCyndy Ishida D->getASTContext().getCurrentKeyFunction(D);
3152c93beccSCyndy Ishida // If this class has a key function, then there is a vtable, possibly internal
3162c93beccSCyndy Ishida // though.
3172c93beccSCyndy Ishida if (KeyFunctionD) {
3182c93beccSCyndy Ishida switch (KeyFunctionD->getTemplateSpecializationKind()) {
3192c93beccSCyndy Ishida case TSK_Undeclared:
3202c93beccSCyndy Ishida case TSK_ExplicitSpecialization:
3212c93beccSCyndy Ishida case TSK_ImplicitInstantiation:
3222c93beccSCyndy Ishida case TSK_ExplicitInstantiationDefinition:
3232c93beccSCyndy Ishida return true;
3242c93beccSCyndy Ishida case TSK_ExplicitInstantiationDeclaration:
3252c93beccSCyndy Ishida llvm_unreachable(
3262c93beccSCyndy Ishida "Unexpected TemplateSpecializationKind for key function");
3272c93beccSCyndy Ishida }
3282c93beccSCyndy Ishida } else if (D->isAbstract()) {
3292c93beccSCyndy Ishida // If the class is abstract and it doesn't have a key function, it is a
3302c93beccSCyndy Ishida // 'pure' virtual class. It doesn't need a vtable.
3312c93beccSCyndy Ishida return false;
3322c93beccSCyndy Ishida }
3332c93beccSCyndy Ishida
3342c93beccSCyndy Ishida switch (D->getTemplateSpecializationKind()) {
3352c93beccSCyndy Ishida case TSK_Undeclared:
3362c93beccSCyndy Ishida case TSK_ExplicitSpecialization:
3372c93beccSCyndy Ishida case TSK_ImplicitInstantiation:
3382c93beccSCyndy Ishida return false;
3392c93beccSCyndy Ishida
3402c93beccSCyndy Ishida case TSK_ExplicitInstantiationDeclaration:
3412c93beccSCyndy Ishida case TSK_ExplicitInstantiationDefinition:
3422c93beccSCyndy Ishida return true;
3432c93beccSCyndy Ishida }
3442c93beccSCyndy Ishida
3452c93beccSCyndy Ishida llvm_unreachable("Invalid TemplateSpecializationKind!");
3462c93beccSCyndy Ishida }
3472c93beccSCyndy Ishida
getVTableLinkage(const CXXRecordDecl * D)3482c93beccSCyndy Ishida static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) {
3492c93beccSCyndy Ishida assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable");
3502c93beccSCyndy Ishida assert(D->isExternallyVisible() && "Record should be externally visible");
3512c93beccSCyndy Ishida if (D->getVisibility() == HiddenVisibility)
3522c93beccSCyndy Ishida return CXXLinkage::PrivateLinkage;
3532c93beccSCyndy Ishida
3542c93beccSCyndy Ishida const CXXMethodDecl *KeyFunctionD =
3552c93beccSCyndy Ishida D->getASTContext().getCurrentKeyFunction(D);
3562c93beccSCyndy Ishida if (KeyFunctionD) {
3572c93beccSCyndy Ishida // If this class has a key function, use that to determine the
3582c93beccSCyndy Ishida // linkage of the vtable.
3592c93beccSCyndy Ishida switch (KeyFunctionD->getTemplateSpecializationKind()) {
3602c93beccSCyndy Ishida case TSK_Undeclared:
3612c93beccSCyndy Ishida case TSK_ExplicitSpecialization:
3622c93beccSCyndy Ishida if (isInlined(KeyFunctionD))
3632c93beccSCyndy Ishida return CXXLinkage::LinkOnceODRLinkage;
3642c93beccSCyndy Ishida return CXXLinkage::ExternalLinkage;
3652c93beccSCyndy Ishida case TSK_ImplicitInstantiation:
3662c93beccSCyndy Ishida llvm_unreachable("No external vtable for implicit instantiations");
3672c93beccSCyndy Ishida case TSK_ExplicitInstantiationDefinition:
3682c93beccSCyndy Ishida return CXXLinkage::WeakODRLinkage;
3692c93beccSCyndy Ishida case TSK_ExplicitInstantiationDeclaration:
3702c93beccSCyndy Ishida llvm_unreachable(
3712c93beccSCyndy Ishida "Unexpected TemplateSpecializationKind for key function");
3722c93beccSCyndy Ishida }
3732c93beccSCyndy Ishida }
3742c93beccSCyndy Ishida
3752c93beccSCyndy Ishida switch (D->getTemplateSpecializationKind()) {
3762c93beccSCyndy Ishida case TSK_Undeclared:
3772c93beccSCyndy Ishida case TSK_ExplicitSpecialization:
3782c93beccSCyndy Ishida case TSK_ImplicitInstantiation:
3792c93beccSCyndy Ishida return CXXLinkage::LinkOnceODRLinkage;
3802c93beccSCyndy Ishida case TSK_ExplicitInstantiationDeclaration:
3812c93beccSCyndy Ishida case TSK_ExplicitInstantiationDefinition:
3822c93beccSCyndy Ishida return CXXLinkage::WeakODRLinkage;
3832c93beccSCyndy Ishida }
3842c93beccSCyndy Ishida
3852c93beccSCyndy Ishida llvm_unreachable("Invalid TemplateSpecializationKind!");
3862c93beccSCyndy Ishida }
3872c93beccSCyndy Ishida
isRTTIWeakDef(const CXXRecordDecl * D)3882c93beccSCyndy Ishida static bool isRTTIWeakDef(const CXXRecordDecl *D) {
3892c93beccSCyndy Ishida if (D->hasAttr<WeakAttr>())
3902c93beccSCyndy Ishida return true;
3912c93beccSCyndy Ishida
3922c93beccSCyndy Ishida if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr)
3932c93beccSCyndy Ishida return true;
3942c93beccSCyndy Ishida
3952c93beccSCyndy Ishida if (D->isDynamicClass())
3962c93beccSCyndy Ishida return getVTableLinkage(D) != CXXLinkage::ExternalLinkage;
3972c93beccSCyndy Ishida
3982c93beccSCyndy Ishida return false;
3992c93beccSCyndy Ishida }
4002c93beccSCyndy Ishida
hasRTTI(const CXXRecordDecl * D)4012c93beccSCyndy Ishida static bool hasRTTI(const CXXRecordDecl *D) {
4022c93beccSCyndy Ishida if (!D->getASTContext().getLangOpts().RTTI)
4032c93beccSCyndy Ishida return false;
4042c93beccSCyndy Ishida
4052c93beccSCyndy Ishida if (!D->hasDefinition())
4062c93beccSCyndy Ishida return false;
4072c93beccSCyndy Ishida
4082c93beccSCyndy Ishida if (!D->isDynamicClass())
4092c93beccSCyndy Ishida return false;
4102c93beccSCyndy Ishida
4112c93beccSCyndy Ishida // Don't emit weak-def RTTI information. InstallAPI cannot reliably determine
4122c93beccSCyndy Ishida // if the final binary will have those weak defined RTTI symbols. This depends
4132c93beccSCyndy Ishida // on the optimization level and if the class has been instantiated and used.
4142c93beccSCyndy Ishida //
4152c93beccSCyndy Ishida // Luckily, the Apple static linker doesn't need those weak defined RTTI
4162c93beccSCyndy Ishida // symbols for linking. They are only needed by the runtime linker. That means
4172c93beccSCyndy Ishida // they can be safely dropped.
4182c93beccSCyndy Ishida if (isRTTIWeakDef(D))
4192c93beccSCyndy Ishida return false;
4202c93beccSCyndy Ishida
4212c93beccSCyndy Ishida return true;
4222c93beccSCyndy Ishida }
4232c93beccSCyndy Ishida
4242c93beccSCyndy Ishida std::string
getMangledCXXRTTIName(const CXXRecordDecl * D) const4252c93beccSCyndy Ishida InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
4262c93beccSCyndy Ishida SmallString<256> Name;
4272c93beccSCyndy Ishida raw_svector_ostream NameStream(Name);
4282c93beccSCyndy Ishida MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream);
4292c93beccSCyndy Ishida
4302c93beccSCyndy Ishida return getBackendMangledName(Name);
4312c93beccSCyndy Ishida }
4322c93beccSCyndy Ishida
getMangledCXXRTTI(const CXXRecordDecl * D) const4332c93beccSCyndy Ishida std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
4342c93beccSCyndy Ishida SmallString<256> Name;
4352c93beccSCyndy Ishida raw_svector_ostream NameStream(Name);
4362c93beccSCyndy Ishida MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream);
4372c93beccSCyndy Ishida
4382c93beccSCyndy Ishida return getBackendMangledName(Name);
4392c93beccSCyndy Ishida }
4402c93beccSCyndy Ishida
4412c93beccSCyndy Ishida std::string
getMangledCXXVTableName(const CXXRecordDecl * D) const4422c93beccSCyndy Ishida InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const {
4432c93beccSCyndy Ishida SmallString<256> Name;
4442c93beccSCyndy Ishida raw_svector_ostream NameStream(Name);
4452c93beccSCyndy Ishida MC->mangleCXXVTable(D, NameStream);
4462c93beccSCyndy Ishida
4472c93beccSCyndy Ishida return getBackendMangledName(Name);
4482c93beccSCyndy Ishida }
4492c93beccSCyndy Ishida
getMangledCXXThunk(const GlobalDecl & D,const ThunkInfo & Thunk,bool ElideOverrideInfo) const450*1b8ab2f0SOliver Hunt std::string InstallAPIVisitor::getMangledCXXThunk(
451*1b8ab2f0SOliver Hunt const GlobalDecl &D, const ThunkInfo &Thunk, bool ElideOverrideInfo) const {
4522c93beccSCyndy Ishida SmallString<256> Name;
4532c93beccSCyndy Ishida raw_svector_ostream NameStream(Name);
4542c93beccSCyndy Ishida const auto *Method = cast<CXXMethodDecl>(D.getDecl());
4552c93beccSCyndy Ishida if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(Method))
456*1b8ab2f0SOliver Hunt MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk, ElideOverrideInfo,
457*1b8ab2f0SOliver Hunt NameStream);
4582c93beccSCyndy Ishida else
459*1b8ab2f0SOliver Hunt MC->mangleThunk(Method, Thunk, ElideOverrideInfo, NameStream);
4602c93beccSCyndy Ishida
4612c93beccSCyndy Ishida return getBackendMangledName(Name);
4622c93beccSCyndy Ishida }
4632c93beccSCyndy Ishida
getMangledCtorDtor(const CXXMethodDecl * D,int Type) const4642c93beccSCyndy Ishida std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D,
4652c93beccSCyndy Ishida int Type) const {
4662c93beccSCyndy Ishida SmallString<256> Name;
4672c93beccSCyndy Ishida raw_svector_ostream NameStream(Name);
4682c93beccSCyndy Ishida GlobalDecl GD;
4692c93beccSCyndy Ishida if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(D))
4702c93beccSCyndy Ishida GD = GlobalDecl(Ctor, CXXCtorType(Type));
4712c93beccSCyndy Ishida else {
4722c93beccSCyndy Ishida const auto *Dtor = cast<CXXDestructorDecl>(D);
4732c93beccSCyndy Ishida GD = GlobalDecl(Dtor, CXXDtorType(Type));
4742c93beccSCyndy Ishida }
4752c93beccSCyndy Ishida MC->mangleName(GD, NameStream);
4762c93beccSCyndy Ishida return getBackendMangledName(Name);
4772c93beccSCyndy Ishida }
4782c93beccSCyndy Ishida
emitVTableSymbols(const CXXRecordDecl * D,const AvailabilityInfo & Avail,const HeaderType Access,bool EmittedVTable)4792c93beccSCyndy Ishida void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
4802c93beccSCyndy Ishida const AvailabilityInfo &Avail,
4812c93beccSCyndy Ishida const HeaderType Access,
4822c93beccSCyndy Ishida bool EmittedVTable) {
4832c93beccSCyndy Ishida if (hasVTable(D)) {
4842c93beccSCyndy Ishida EmittedVTable = true;
4852c93beccSCyndy Ishida const CXXLinkage VTableLinkage = getVTableLinkage(D);
4862c93beccSCyndy Ishida if (VTableLinkage == CXXLinkage::ExternalLinkage ||
4872c93beccSCyndy Ishida VTableLinkage == CXXLinkage::WeakODRLinkage) {
4882c93beccSCyndy Ishida const std::string Name = getMangledCXXVTableName(D);
4892c93beccSCyndy Ishida const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;
490f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
491f2794cceSCyndy Ishida GlobalRecord::Kind::Variable, Avail,
492f2794cceSCyndy Ishida D, Access, getFlags(WeakDef));
493f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
4942c93beccSCyndy Ishida if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) {
4952c93beccSCyndy Ishida VTableContextBase *VTable = D->getASTContext().getVTableContext();
4962c93beccSCyndy Ishida auto AddThunk = [&](GlobalDecl GD) {
4972c93beccSCyndy Ishida const ItaniumVTableContext::ThunkInfoVectorTy *Thunks =
4982c93beccSCyndy Ishida VTable->getThunkInfo(GD);
4992c93beccSCyndy Ishida if (!Thunks)
5002c93beccSCyndy Ishida return;
5012c93beccSCyndy Ishida
5022c93beccSCyndy Ishida for (const auto &Thunk : *Thunks) {
503*1b8ab2f0SOliver Hunt const std::string Name =
504*1b8ab2f0SOliver Hunt getMangledCXXThunk(GD, Thunk, /*ElideOverrideInfo=*/true);
505f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
506f2794cceSCyndy Ishida GlobalRecord::Kind::Function,
507f2794cceSCyndy Ishida Avail, GD.getDecl(), Access);
508f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
5092c93beccSCyndy Ishida }
5102c93beccSCyndy Ishida };
5112c93beccSCyndy Ishida
5122c93beccSCyndy Ishida for (const auto *Method : D->methods()) {
5132c93beccSCyndy Ishida if (isa<CXXConstructorDecl>(Method) || !Method->isVirtual())
5142c93beccSCyndy Ishida continue;
5152c93beccSCyndy Ishida
5162c93beccSCyndy Ishida if (auto Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
5172c93beccSCyndy Ishida // Skip default destructor.
5182c93beccSCyndy Ishida if (Dtor->isDefaulted())
5192c93beccSCyndy Ishida continue;
5202c93beccSCyndy Ishida AddThunk({Dtor, Dtor_Deleting});
5212c93beccSCyndy Ishida AddThunk({Dtor, Dtor_Complete});
5222c93beccSCyndy Ishida } else
5232c93beccSCyndy Ishida AddThunk(Method);
5242c93beccSCyndy Ishida }
5252c93beccSCyndy Ishida }
5262c93beccSCyndy Ishida }
5272c93beccSCyndy Ishida }
5282c93beccSCyndy Ishida
5292c93beccSCyndy Ishida if (!EmittedVTable)
5302c93beccSCyndy Ishida return;
5312c93beccSCyndy Ishida
5322c93beccSCyndy Ishida if (hasRTTI(D)) {
5332c93beccSCyndy Ishida std::string Name = getMangledCXXRTTI(D);
534f2794cceSCyndy Ishida auto [GR, FA] =
5352c93beccSCyndy Ishida Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
5362c93beccSCyndy Ishida GlobalRecord::Kind::Variable, Avail, D, Access);
537f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
5382c93beccSCyndy Ishida
5392c93beccSCyndy Ishida Name = getMangledCXXRTTIName(D);
540f2794cceSCyndy Ishida auto [NamedGR, NamedFA] =
5412c93beccSCyndy Ishida Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
5422c93beccSCyndy Ishida GlobalRecord::Kind::Variable, Avail, D, Access);
543f2794cceSCyndy Ishida Ctx.Verifier->verify(NamedGR, NamedFA);
5442c93beccSCyndy Ishida }
5452c93beccSCyndy Ishida
5462c93beccSCyndy Ishida for (const auto &It : D->bases()) {
5472c93beccSCyndy Ishida const CXXRecordDecl *Base =
5482c93beccSCyndy Ishida cast<CXXRecordDecl>(It.getType()->castAs<RecordType>()->getDecl());
5492c93beccSCyndy Ishida const auto BaseAccess = getAccessForDecl(Base);
5502c93beccSCyndy Ishida if (!BaseAccess)
5512c93beccSCyndy Ishida continue;
5522c93beccSCyndy Ishida const AvailabilityInfo BaseAvail = AvailabilityInfo::createFromDecl(Base);
5532c93beccSCyndy Ishida emitVTableSymbols(Base, BaseAvail, *BaseAccess, /*EmittedVTable=*/true);
5542c93beccSCyndy Ishida }
5552c93beccSCyndy Ishida }
5562c93beccSCyndy Ishida
VisitCXXRecordDecl(const CXXRecordDecl * D)5572c93beccSCyndy Ishida bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) {
5582c93beccSCyndy Ishida if (!D->isCompleteDefinition())
5592c93beccSCyndy Ishida return true;
5602c93beccSCyndy Ishida
5612c93beccSCyndy Ishida // Skip templated classes.
5622c93beccSCyndy Ishida if (D->getDescribedClassTemplate() != nullptr)
5632c93beccSCyndy Ishida return true;
5642c93beccSCyndy Ishida
5652c93beccSCyndy Ishida // Skip partial templated classes too.
5662c93beccSCyndy Ishida if (isa<ClassTemplatePartialSpecializationDecl>(D))
5672c93beccSCyndy Ishida return true;
5682c93beccSCyndy Ishida
5692c93beccSCyndy Ishida auto Access = getAccessForDecl(D);
5702c93beccSCyndy Ishida if (!Access)
5712c93beccSCyndy Ishida return true;
5722c93beccSCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
5732c93beccSCyndy Ishida
5742c93beccSCyndy Ishida // Check whether to emit the vtable/rtti symbols.
5752c93beccSCyndy Ishida if (isExported(D))
5762c93beccSCyndy Ishida emitVTableSymbols(D, Avail, *Access);
5772c93beccSCyndy Ishida
5782c93beccSCyndy Ishida TemplateSpecializationKind ClassSK = TSK_Undeclared;
5792c93beccSCyndy Ishida bool KeepInlineAsWeak = false;
5802c93beccSCyndy Ishida if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
5812c93beccSCyndy Ishida ClassSK = Templ->getTemplateSpecializationKind();
5822c93beccSCyndy Ishida if (ClassSK == TSK_ExplicitInstantiationDeclaration)
5832c93beccSCyndy Ishida KeepInlineAsWeak = true;
5842c93beccSCyndy Ishida }
5852c93beccSCyndy Ishida
5862c93beccSCyndy Ishida // Record the class methods.
5872c93beccSCyndy Ishida for (const auto *M : D->methods()) {
5882c93beccSCyndy Ishida // Inlined methods are usually not emitted, except when it comes from a
5892c93beccSCyndy Ishida // specialized template.
5902c93beccSCyndy Ishida bool WeakDef = false;
5912c93beccSCyndy Ishida if (isInlined(M)) {
5922c93beccSCyndy Ishida if (!KeepInlineAsWeak)
5932c93beccSCyndy Ishida continue;
5942c93beccSCyndy Ishida
5952c93beccSCyndy Ishida WeakDef = true;
5962c93beccSCyndy Ishida }
5972c93beccSCyndy Ishida
5982c93beccSCyndy Ishida if (!isExported(M))
5992c93beccSCyndy Ishida continue;
6002c93beccSCyndy Ishida
6012c93beccSCyndy Ishida switch (M->getTemplateSpecializationKind()) {
6022c93beccSCyndy Ishida case TSK_Undeclared:
6032c93beccSCyndy Ishida case TSK_ExplicitSpecialization:
6042c93beccSCyndy Ishida break;
6052c93beccSCyndy Ishida case TSK_ImplicitInstantiation:
6062c93beccSCyndy Ishida continue;
6072c93beccSCyndy Ishida case TSK_ExplicitInstantiationDeclaration:
6082c93beccSCyndy Ishida if (ClassSK == TSK_ExplicitInstantiationDeclaration)
6092c93beccSCyndy Ishida WeakDef = true;
6102c93beccSCyndy Ishida break;
6112c93beccSCyndy Ishida case TSK_ExplicitInstantiationDefinition:
6122c93beccSCyndy Ishida WeakDef = true;
6132c93beccSCyndy Ishida break;
6142c93beccSCyndy Ishida }
6152c93beccSCyndy Ishida
6162c93beccSCyndy Ishida if (!M->isUserProvided())
6172c93beccSCyndy Ishida continue;
6182c93beccSCyndy Ishida
6192c93beccSCyndy Ishida // Methods that are deleted are not exported.
6202c93beccSCyndy Ishida if (M->isDeleted())
6212c93beccSCyndy Ishida continue;
6222c93beccSCyndy Ishida
6232c93beccSCyndy Ishida const auto Access = getAccessForDecl(M);
6242c93beccSCyndy Ishida if (!Access)
6252c93beccSCyndy Ishida return true;
6262c93beccSCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(M);
6272c93beccSCyndy Ishida
6282c93beccSCyndy Ishida if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(M)) {
6292c93beccSCyndy Ishida // Defaulted constructors are not exported.
6302c93beccSCyndy Ishida if (Ctor->isDefaulted())
6312c93beccSCyndy Ishida continue;
6322c93beccSCyndy Ishida
6332c93beccSCyndy Ishida std::string Name = getMangledCtorDtor(M, Ctor_Base);
634f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
635f2794cceSCyndy Ishida GlobalRecord::Kind::Function, Avail,
636f2794cceSCyndy Ishida D, *Access, getFlags(WeakDef));
637f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
6382c93beccSCyndy Ishida
6392c93beccSCyndy Ishida if (!D->isAbstract()) {
6402c93beccSCyndy Ishida std::string Name = getMangledCtorDtor(M, Ctor_Complete);
641f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(
642f2794cceSCyndy Ishida Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
643f2794cceSCyndy Ishida D, *Access, getFlags(WeakDef));
644f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
6452c93beccSCyndy Ishida }
6462c93beccSCyndy Ishida
6472c93beccSCyndy Ishida continue;
6482c93beccSCyndy Ishida }
6492c93beccSCyndy Ishida
6502c93beccSCyndy Ishida if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(M)) {
6512c93beccSCyndy Ishida // Defaulted destructors are not exported.
6522c93beccSCyndy Ishida if (Dtor->isDefaulted())
6532c93beccSCyndy Ishida continue;
6542c93beccSCyndy Ishida
6552c93beccSCyndy Ishida std::string Name = getMangledCtorDtor(M, Dtor_Base);
656f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
657f2794cceSCyndy Ishida GlobalRecord::Kind::Function, Avail,
658f2794cceSCyndy Ishida D, *Access, getFlags(WeakDef));
659f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
6602c93beccSCyndy Ishida
6612c93beccSCyndy Ishida Name = getMangledCtorDtor(M, Dtor_Complete);
662f2794cceSCyndy Ishida auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal(
663f2794cceSCyndy Ishida Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D,
664f2794cceSCyndy Ishida *Access, getFlags(WeakDef));
665f2794cceSCyndy Ishida Ctx.Verifier->verify(CompleteGR, CompleteFA);
6662c93beccSCyndy Ishida
6672c93beccSCyndy Ishida if (Dtor->isVirtual()) {
6682c93beccSCyndy Ishida Name = getMangledCtorDtor(M, Dtor_Deleting);
669f2794cceSCyndy Ishida auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal(
670f2794cceSCyndy Ishida Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
671f2794cceSCyndy Ishida D, *Access, getFlags(WeakDef));
672f2794cceSCyndy Ishida Ctx.Verifier->verify(VirtualGR, VirtualFA);
6732c93beccSCyndy Ishida }
6742c93beccSCyndy Ishida
6752c93beccSCyndy Ishida continue;
6762c93beccSCyndy Ishida }
6772c93beccSCyndy Ishida
6782c93beccSCyndy Ishida // Though abstract methods can map to exports, this is generally unexpected.
6792c93beccSCyndy Ishida // Except in the case of destructors. Only ignore pure virtuals after
6802c93beccSCyndy Ishida // checking if the member function was a destructor.
6812c93beccSCyndy Ishida if (M->isPureVirtual())
6822c93beccSCyndy Ishida continue;
6832c93beccSCyndy Ishida
6842c93beccSCyndy Ishida std::string Name = getMangledName(M);
685f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
686936519f2SCyndy Ishida GlobalRecord::Kind::Function, Avail, M,
687f2794cceSCyndy Ishida *Access, getFlags(WeakDef));
688f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
6892c93beccSCyndy Ishida }
6902c93beccSCyndy Ishida
6912c93beccSCyndy Ishida if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
6922c93beccSCyndy Ishida if (!Templ->isExplicitInstantiationOrSpecialization())
6932c93beccSCyndy Ishida return true;
6942c93beccSCyndy Ishida }
6952c93beccSCyndy Ishida
6962c93beccSCyndy Ishida using var_iter = CXXRecordDecl::specific_decl_iterator<VarDecl>;
6972c93beccSCyndy Ishida using var_range = iterator_range<var_iter>;
6982c93beccSCyndy Ishida for (const auto *Var : var_range(D->decls())) {
6992c93beccSCyndy Ishida // Skip const static member variables.
7002c93beccSCyndy Ishida // \code
7012c93beccSCyndy Ishida // struct S {
7022c93beccSCyndy Ishida // static const int x = 0;
7032c93beccSCyndy Ishida // };
7042c93beccSCyndy Ishida // \endcode
7052c93beccSCyndy Ishida if (Var->isStaticDataMember() && Var->hasInit())
7062c93beccSCyndy Ishida continue;
7072c93beccSCyndy Ishida
7082c93beccSCyndy Ishida // Skip unexported var decls.
7092c93beccSCyndy Ishida if (!isExported(Var))
7102c93beccSCyndy Ishida continue;
7112c93beccSCyndy Ishida
7122c93beccSCyndy Ishida const std::string Name = getMangledName(Var);
7132c93beccSCyndy Ishida const auto Access = getAccessForDecl(Var);
7142c93beccSCyndy Ishida if (!Access)
7152c93beccSCyndy Ishida return true;
7162c93beccSCyndy Ishida const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var);
7172c93beccSCyndy Ishida const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak;
7182c93beccSCyndy Ishida
719f2794cceSCyndy Ishida auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
720f2794cceSCyndy Ishida GlobalRecord::Kind::Variable, Avail, D,
721f2794cceSCyndy Ishida *Access, getFlags(WeakDef));
722f2794cceSCyndy Ishida Ctx.Verifier->verify(GR, FA);
7232c93beccSCyndy Ishida }
7242c93beccSCyndy Ishida
72550ae8a2aSCyndy Ishida return true;
72650ae8a2aSCyndy Ishida }
72750ae8a2aSCyndy Ishida
728c6cbf81cSCyndy Ishida } // namespace clang::installapi
729