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