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 auto [Category, FA] = Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, 209 Avail, D, *Access); 210 recordObjCInstanceVariables(D->getASTContext(), Category, InterfaceName, 211 D->ivars()); 212 return true; 213 } 214 215 bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) { 216 // Skip function parameters. 217 if (isa<ParmVarDecl>(D)) 218 return true; 219 220 // Skip variables in records. They are handled seperately for C++. 221 if (D->getDeclContext()->isRecord()) 222 return true; 223 224 // Skip anything inside functions or methods. 225 if (!D->isDefinedOutsideFunctionOrMethod()) 226 return true; 227 228 // If this is a template but not specialization or instantiation, skip. 229 if (D->getASTContext().getTemplateOrSpecializationInfo(D) && 230 D->getTemplateSpecializationKind() == TSK_Undeclared) 231 return true; 232 233 // Skip over declarations that access could not collected for. 234 auto Access = getAccessForDecl(D); 235 if (!Access) 236 return true; 237 238 const RecordLinkage Linkage = 239 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal; 240 const bool WeakDef = D->hasAttr<WeakAttr>(); 241 const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None; 242 const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D); 243 auto [GR, FA] = Ctx.Slice->addGlobal(getMangledName(D), Linkage, 244 GlobalRecord::Kind::Variable, Avail, D, 245 *Access, getFlags(WeakDef, ThreadLocal)); 246 Ctx.Verifier->verify(GR, FA); 247 return true; 248 } 249 250 bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { 251 if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(D)) { 252 // Skip member function in class templates. 253 if (M->getParent()->getDescribedClassTemplate() != nullptr) 254 return true; 255 256 // Skip methods in CXX RecordDecls. 257 for (auto P : D->getASTContext().getParents(*M)) { 258 if (P.get<CXXRecordDecl>()) 259 return true; 260 } 261 262 // Skip CXX ConstructorDecls and DestructorDecls. 263 if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M)) 264 return true; 265 } 266 267 // Skip templated functions. 268 switch (D->getTemplatedKind()) { 269 case FunctionDecl::TK_NonTemplate: 270 case FunctionDecl::TK_DependentNonTemplate: 271 break; 272 case FunctionDecl::TK_MemberSpecialization: 273 case FunctionDecl::TK_FunctionTemplateSpecialization: 274 if (auto *TempInfo = D->getTemplateSpecializationInfo()) { 275 if (!TempInfo->isExplicitInstantiationOrSpecialization()) 276 return true; 277 } 278 break; 279 case FunctionDecl::TK_FunctionTemplate: 280 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: 281 return true; 282 } 283 284 auto Access = getAccessForDecl(D); 285 if (!Access) 286 return true; 287 auto Name = getMangledName(D); 288 const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D); 289 const bool ExplicitInstantiation = D->getTemplateSpecializationKind() == 290 TSK_ExplicitInstantiationDeclaration; 291 const bool WeakDef = ExplicitInstantiation || D->hasAttr<WeakAttr>(); 292 const bool Inlined = isInlined(D); 293 const RecordLinkage Linkage = (Inlined || !isExported(D)) 294 ? RecordLinkage::Internal 295 : RecordLinkage::Exported; 296 auto [GR, FA] = 297 Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail, 298 D, *Access, getFlags(WeakDef), Inlined); 299 Ctx.Verifier->verify(GR, FA); 300 return true; 301 } 302 303 static bool hasVTable(const CXXRecordDecl *D) { 304 // Check if vtable symbols should be emitted, only dynamic classes need 305 // vtables. 306 if (!D->hasDefinition() || !D->isDynamicClass()) 307 return false; 308 309 assert(D->isExternallyVisible() && "Should be externally visible"); 310 assert(D->isCompleteDefinition() && "Only works on complete definitions"); 311 312 const CXXMethodDecl *KeyFunctionD = 313 D->getASTContext().getCurrentKeyFunction(D); 314 // If this class has a key function, then there is a vtable, possibly internal 315 // though. 316 if (KeyFunctionD) { 317 switch (KeyFunctionD->getTemplateSpecializationKind()) { 318 case TSK_Undeclared: 319 case TSK_ExplicitSpecialization: 320 case TSK_ImplicitInstantiation: 321 case TSK_ExplicitInstantiationDefinition: 322 return true; 323 case TSK_ExplicitInstantiationDeclaration: 324 llvm_unreachable( 325 "Unexpected TemplateSpecializationKind for key function"); 326 } 327 } else if (D->isAbstract()) { 328 // If the class is abstract and it doesn't have a key function, it is a 329 // 'pure' virtual class. It doesn't need a vtable. 330 return false; 331 } 332 333 switch (D->getTemplateSpecializationKind()) { 334 case TSK_Undeclared: 335 case TSK_ExplicitSpecialization: 336 case TSK_ImplicitInstantiation: 337 return false; 338 339 case TSK_ExplicitInstantiationDeclaration: 340 case TSK_ExplicitInstantiationDefinition: 341 return true; 342 } 343 344 llvm_unreachable("Invalid TemplateSpecializationKind!"); 345 } 346 347 static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) { 348 assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable"); 349 assert(D->isExternallyVisible() && "Record should be externally visible"); 350 if (D->getVisibility() == HiddenVisibility) 351 return CXXLinkage::PrivateLinkage; 352 353 const CXXMethodDecl *KeyFunctionD = 354 D->getASTContext().getCurrentKeyFunction(D); 355 if (KeyFunctionD) { 356 // If this class has a key function, use that to determine the 357 // linkage of the vtable. 358 switch (KeyFunctionD->getTemplateSpecializationKind()) { 359 case TSK_Undeclared: 360 case TSK_ExplicitSpecialization: 361 if (isInlined(KeyFunctionD)) 362 return CXXLinkage::LinkOnceODRLinkage; 363 return CXXLinkage::ExternalLinkage; 364 case TSK_ImplicitInstantiation: 365 llvm_unreachable("No external vtable for implicit instantiations"); 366 case TSK_ExplicitInstantiationDefinition: 367 return CXXLinkage::WeakODRLinkage; 368 case TSK_ExplicitInstantiationDeclaration: 369 llvm_unreachable( 370 "Unexpected TemplateSpecializationKind for key function"); 371 } 372 } 373 374 switch (D->getTemplateSpecializationKind()) { 375 case TSK_Undeclared: 376 case TSK_ExplicitSpecialization: 377 case TSK_ImplicitInstantiation: 378 return CXXLinkage::LinkOnceODRLinkage; 379 case TSK_ExplicitInstantiationDeclaration: 380 case TSK_ExplicitInstantiationDefinition: 381 return CXXLinkage::WeakODRLinkage; 382 } 383 384 llvm_unreachable("Invalid TemplateSpecializationKind!"); 385 } 386 387 static bool isRTTIWeakDef(const CXXRecordDecl *D) { 388 if (D->hasAttr<WeakAttr>()) 389 return true; 390 391 if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr) 392 return true; 393 394 if (D->isDynamicClass()) 395 return getVTableLinkage(D) != CXXLinkage::ExternalLinkage; 396 397 return false; 398 } 399 400 static bool hasRTTI(const CXXRecordDecl *D) { 401 if (!D->getASTContext().getLangOpts().RTTI) 402 return false; 403 404 if (!D->hasDefinition()) 405 return false; 406 407 if (!D->isDynamicClass()) 408 return false; 409 410 // Don't emit weak-def RTTI information. InstallAPI cannot reliably determine 411 // if the final binary will have those weak defined RTTI symbols. This depends 412 // on the optimization level and if the class has been instantiated and used. 413 // 414 // Luckily, the Apple static linker doesn't need those weak defined RTTI 415 // symbols for linking. They are only needed by the runtime linker. That means 416 // they can be safely dropped. 417 if (isRTTIWeakDef(D)) 418 return false; 419 420 return true; 421 } 422 423 std::string 424 InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const { 425 SmallString<256> Name; 426 raw_svector_ostream NameStream(Name); 427 MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream); 428 429 return getBackendMangledName(Name); 430 } 431 432 std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const { 433 SmallString<256> Name; 434 raw_svector_ostream NameStream(Name); 435 MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream); 436 437 return getBackendMangledName(Name); 438 } 439 440 std::string 441 InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const { 442 SmallString<256> Name; 443 raw_svector_ostream NameStream(Name); 444 MC->mangleCXXVTable(D, NameStream); 445 446 return getBackendMangledName(Name); 447 } 448 449 std::string 450 InstallAPIVisitor::getMangledCXXThunk(const GlobalDecl &D, 451 const ThunkInfo &Thunk) 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.This, NameStream); 457 else 458 MC->mangleThunk(Method, Thunk, NameStream); 459 460 return getBackendMangledName(Name); 461 } 462 463 std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D, 464 int Type) const { 465 SmallString<256> Name; 466 raw_svector_ostream NameStream(Name); 467 GlobalDecl GD; 468 if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) 469 GD = GlobalDecl(Ctor, CXXCtorType(Type)); 470 else { 471 const auto *Dtor = cast<CXXDestructorDecl>(D); 472 GD = GlobalDecl(Dtor, CXXDtorType(Type)); 473 } 474 MC->mangleName(GD, NameStream); 475 return getBackendMangledName(Name); 476 } 477 478 void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, 479 const AvailabilityInfo &Avail, 480 const HeaderType Access, 481 bool EmittedVTable) { 482 if (hasVTable(D)) { 483 EmittedVTable = true; 484 const CXXLinkage VTableLinkage = getVTableLinkage(D); 485 if (VTableLinkage == CXXLinkage::ExternalLinkage || 486 VTableLinkage == CXXLinkage::WeakODRLinkage) { 487 const std::string Name = getMangledCXXVTableName(D); 488 const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage; 489 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 490 GlobalRecord::Kind::Variable, Avail, 491 D, Access, getFlags(WeakDef)); 492 Ctx.Verifier->verify(GR, FA); 493 if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) { 494 VTableContextBase *VTable = D->getASTContext().getVTableContext(); 495 auto AddThunk = [&](GlobalDecl GD) { 496 const ItaniumVTableContext::ThunkInfoVectorTy *Thunks = 497 VTable->getThunkInfo(GD); 498 if (!Thunks) 499 return; 500 501 for (const auto &Thunk : *Thunks) { 502 const std::string Name = getMangledCXXThunk(GD, Thunk); 503 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 504 GlobalRecord::Kind::Function, 505 Avail, GD.getDecl(), Access); 506 Ctx.Verifier->verify(GR, FA); 507 } 508 }; 509 510 for (const auto *Method : D->methods()) { 511 if (isa<CXXConstructorDecl>(Method) || !Method->isVirtual()) 512 continue; 513 514 if (auto Dtor = dyn_cast<CXXDestructorDecl>(Method)) { 515 // Skip default destructor. 516 if (Dtor->isDefaulted()) 517 continue; 518 AddThunk({Dtor, Dtor_Deleting}); 519 AddThunk({Dtor, Dtor_Complete}); 520 } else 521 AddThunk(Method); 522 } 523 } 524 } 525 } 526 527 if (!EmittedVTable) 528 return; 529 530 if (hasRTTI(D)) { 531 std::string Name = getMangledCXXRTTI(D); 532 auto [GR, FA] = 533 Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 534 GlobalRecord::Kind::Variable, Avail, D, Access); 535 Ctx.Verifier->verify(GR, FA); 536 537 Name = getMangledCXXRTTIName(D); 538 auto [NamedGR, NamedFA] = 539 Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 540 GlobalRecord::Kind::Variable, Avail, D, Access); 541 Ctx.Verifier->verify(NamedGR, NamedFA); 542 } 543 544 for (const auto &It : D->bases()) { 545 const CXXRecordDecl *Base = 546 cast<CXXRecordDecl>(It.getType()->castAs<RecordType>()->getDecl()); 547 const auto BaseAccess = getAccessForDecl(Base); 548 if (!BaseAccess) 549 continue; 550 const AvailabilityInfo BaseAvail = AvailabilityInfo::createFromDecl(Base); 551 emitVTableSymbols(Base, BaseAvail, *BaseAccess, /*EmittedVTable=*/true); 552 } 553 } 554 555 bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { 556 if (!D->isCompleteDefinition()) 557 return true; 558 559 // Skip templated classes. 560 if (D->getDescribedClassTemplate() != nullptr) 561 return true; 562 563 // Skip partial templated classes too. 564 if (isa<ClassTemplatePartialSpecializationDecl>(D)) 565 return true; 566 567 auto Access = getAccessForDecl(D); 568 if (!Access) 569 return true; 570 const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D); 571 572 // Check whether to emit the vtable/rtti symbols. 573 if (isExported(D)) 574 emitVTableSymbols(D, Avail, *Access); 575 576 TemplateSpecializationKind ClassSK = TSK_Undeclared; 577 bool KeepInlineAsWeak = false; 578 if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 579 ClassSK = Templ->getTemplateSpecializationKind(); 580 if (ClassSK == TSK_ExplicitInstantiationDeclaration) 581 KeepInlineAsWeak = true; 582 } 583 584 // Record the class methods. 585 for (const auto *M : D->methods()) { 586 // Inlined methods are usually not emitted, except when it comes from a 587 // specialized template. 588 bool WeakDef = false; 589 if (isInlined(M)) { 590 if (!KeepInlineAsWeak) 591 continue; 592 593 WeakDef = true; 594 } 595 596 if (!isExported(M)) 597 continue; 598 599 switch (M->getTemplateSpecializationKind()) { 600 case TSK_Undeclared: 601 case TSK_ExplicitSpecialization: 602 break; 603 case TSK_ImplicitInstantiation: 604 continue; 605 case TSK_ExplicitInstantiationDeclaration: 606 if (ClassSK == TSK_ExplicitInstantiationDeclaration) 607 WeakDef = true; 608 break; 609 case TSK_ExplicitInstantiationDefinition: 610 WeakDef = true; 611 break; 612 } 613 614 if (!M->isUserProvided()) 615 continue; 616 617 // Methods that are deleted are not exported. 618 if (M->isDeleted()) 619 continue; 620 621 const auto Access = getAccessForDecl(M); 622 if (!Access) 623 return true; 624 const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(M); 625 626 if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(M)) { 627 // Defaulted constructors are not exported. 628 if (Ctor->isDefaulted()) 629 continue; 630 631 std::string Name = getMangledCtorDtor(M, Ctor_Base); 632 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 633 GlobalRecord::Kind::Function, Avail, 634 D, *Access, getFlags(WeakDef)); 635 Ctx.Verifier->verify(GR, FA); 636 637 if (!D->isAbstract()) { 638 std::string Name = getMangledCtorDtor(M, Ctor_Complete); 639 auto [GR, FA] = Ctx.Slice->addGlobal( 640 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, 641 D, *Access, getFlags(WeakDef)); 642 Ctx.Verifier->verify(GR, FA); 643 } 644 645 continue; 646 } 647 648 if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(M)) { 649 // Defaulted destructors are not exported. 650 if (Dtor->isDefaulted()) 651 continue; 652 653 std::string Name = getMangledCtorDtor(M, Dtor_Base); 654 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 655 GlobalRecord::Kind::Function, Avail, 656 D, *Access, getFlags(WeakDef)); 657 Ctx.Verifier->verify(GR, FA); 658 659 Name = getMangledCtorDtor(M, Dtor_Complete); 660 auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal( 661 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D, 662 *Access, getFlags(WeakDef)); 663 Ctx.Verifier->verify(CompleteGR, CompleteFA); 664 665 if (Dtor->isVirtual()) { 666 Name = getMangledCtorDtor(M, Dtor_Deleting); 667 auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal( 668 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, 669 D, *Access, getFlags(WeakDef)); 670 Ctx.Verifier->verify(VirtualGR, VirtualFA); 671 } 672 673 continue; 674 } 675 676 // Though abstract methods can map to exports, this is generally unexpected. 677 // Except in the case of destructors. Only ignore pure virtuals after 678 // checking if the member function was a destructor. 679 if (M->isPureVirtual()) 680 continue; 681 682 std::string Name = getMangledName(M); 683 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 684 GlobalRecord::Kind::Function, Avail, D, 685 *Access, getFlags(WeakDef)); 686 Ctx.Verifier->verify(GR, FA); 687 } 688 689 if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 690 if (!Templ->isExplicitInstantiationOrSpecialization()) 691 return true; 692 } 693 694 using var_iter = CXXRecordDecl::specific_decl_iterator<VarDecl>; 695 using var_range = iterator_range<var_iter>; 696 for (const auto *Var : var_range(D->decls())) { 697 // Skip const static member variables. 698 // \code 699 // struct S { 700 // static const int x = 0; 701 // }; 702 // \endcode 703 if (Var->isStaticDataMember() && Var->hasInit()) 704 continue; 705 706 // Skip unexported var decls. 707 if (!isExported(Var)) 708 continue; 709 710 const std::string Name = getMangledName(Var); 711 const auto Access = getAccessForDecl(Var); 712 if (!Access) 713 return true; 714 const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var); 715 const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak; 716 717 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, 718 GlobalRecord::Kind::Variable, Avail, D, 719 *Access, getFlags(WeakDef)); 720 Ctx.Verifier->verify(GR, FA); 721 } 722 723 return true; 724 } 725 726 } // namespace clang::installapi 727