clang: lib/InstallAPI/Visitor.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

16#include "llvm/ADT/StringRef.h"

17#include "llvm/IR/DataLayout.h"

18#include "llvm/IR/Mangler.h"

19

20using namespace llvm;

22

23namespace {

24enum class CXXLinkage {

25 ExternalLinkage,

26 LinkOnceODRLinkage,

27 WeakODRLinkage,

28 PrivateLinkage,

29};

30}

31

33

34

35

41

43 bool HasInlineAttribute = false;

44 bool NoCXXAttr =

47 !D->hasAttr());

48

49

50 for (const auto *RD : D->redecls()) {

51 if (!RD->isInlined())

52 continue;

53 HasInlineAttribute = true;

54 if (!(NoCXXAttr || RD->hasAttr()))

55 continue;

56 if (RD->doesThisDeclarationHaveABody() &&

57 RD->isInlineDefinitionExternallyVisible())

58 return false;

59 }

60

61 if (!HasInlineAttribute)

62 return false;

63

64 return true;

65}

66

69 if (WeakDef)

70 Result |= SymbolFlags::WeakDefined;

71 if (ThreadLocal)

72 Result |= SymbolFlags::ThreadLocalValue;

73

75}

76

84

85std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {

87 if (MC->shouldMangleDeclName(D)) {

88 raw_svector_ostream NStream(Name);

89 MC->mangleName(D, NStream);

90 } else

92

93 return getBackendMangledName(Name);

94}

95

96std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {

98 Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));

99 return std::string(FinalName);

100}

101

102std::optional

103InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {

104 SourceLocation Loc = D->getLocation();

105 if (Loc.isInvalid())

106 return std::nullopt;

107

108

109

110 auto FileLoc = SrcMgr.getFileLoc(Loc);

111 FileID ID = SrcMgr.getFileID(FileLoc);

112 if (ID.isInvalid())

113 return std::nullopt;

114

115 const FileEntry *FE = SrcMgr.getFileEntryForID(ID);

116 if (!FE)

117 return std::nullopt;

118

119 auto Header = Ctx.findAndRecordFile(FE, PP);

120 if (!Header.has_value())

121 return std::nullopt;

122

124 assert(Access != HeaderType::Unknown && "unexpected access level for global");

125 return Access;

126}

127

128

129

130

131

134 if (D->hasAttr())

135 return true;

136

137 return false;

138}

139void InstallAPIVisitor::recordObjCInstanceVariables(

141 const llvm::iterator_range<

143 Ivars) {

146

148 Linkage = RecordLinkage::Unknown;

149

150 else if (ContainerLinkage != RecordLinkage::Unknown)

151 Linkage = ContainerLinkage;

152 for (const auto *IV : Ivars) {

153 auto Access = getAccessForDecl(IV);

154 if (!Access)

155 continue;

156 StringRef Name = IV->getName();

158 auto AC = IV->getCanonicalAccessControl();

159 auto [ObjCIVR, FA] =

160 Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC);

161 Ctx.Verifier->verify(ObjCIVR, FA, SuperClass);

162 }

163}

164

166

168 return true;

169

170

171 auto Access = getAccessForDecl(D);

172 if (!Access)

173 return true;

174

177 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;

179 const bool IsEHType =

182

183 auto [Class, FA] =

184 Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);

185 Ctx.Verifier->verify(Class, FA);

186

187

188 StringRef SuperClassName;

190 SuperClassName = SuperClass->getObjCRuntimeNameAsString();

191

194 return true;

195}

196

198 StringRef CategoryName = D->getName();

199

200 auto Access = getAccessForDecl(D);

201 if (!Access)

202 return true;

205 const StringRef InterfaceName = InterfaceD->getName();

206

208 Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access)

209 .first;

210 recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName,

212 return true;

213}

214

216

218 return true;

219

220

222 return true;

223

224

226 return true;

227

228

231 return true;

232

233

234 auto Access = getAccessForDecl(D);

235 if (!Access)

236 return true;

237

239 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;

240 const bool WeakDef = D->hasAttr();

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

251 if (const CXXMethodDecl *M = dyn_cast(D)) {

252

253 if (M->getParent()->getDescribedClassTemplate() != nullptr)

254 return true;

255

256

259 return true;

260 }

261

262

264 return true;

265 }

266

267

271 break;

275 if (!TempInfo->isExplicitInstantiationOrSpecialization())

276 return true;

277 }

278 break;

281 return true;

282 }

283

284 auto Access = getAccessForDecl(D);

285 if (!Access)

286 return true;

287 auto Name = getMangledName(D);

292 const bool Inlined = isInlined(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

304

305

307 return false;

308

311

314

315

316 if (KeyFunctionD) {

322 return true;

324 llvm_unreachable(

325 "Unexpected TemplateSpecializationKind for key function");

326 }

328

329

330 return false;

331 }

332

337 return false;

338

341 return true;

342 }

343

344 llvm_unreachable("Invalid TemplateSpecializationKind!");

345}

346

349 assert(D->isExternallyVisible() && "Record should be externally visible");

351 return CXXLinkage::PrivateLinkage;

352

355 if (KeyFunctionD) {

356

357

362 return CXXLinkage::LinkOnceODRLinkage;

363 return CXXLinkage::ExternalLinkage;

365 llvm_unreachable("No external vtable for implicit instantiations");

367 return CXXLinkage::WeakODRLinkage;

369 llvm_unreachable(

370 "Unexpected TemplateSpecializationKind for key function");

371 }

372 }

373

378 return CXXLinkage::LinkOnceODRLinkage;

381 return CXXLinkage::WeakODRLinkage;

382 }

383

384 llvm_unreachable("Invalid TemplateSpecializationKind!");

385}

386

388 if (D->hasAttr())

389 return true;

390

392 return true;

393

396

397 return false;

398}

399

402 return false;

403

405 return false;

406

408 return false;

409

410

411

412

413

414

415

416

418 return false;

419

420 return true;

421}

422

423std::string

424InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {

426 raw_svector_ostream NameStream(Name);

427 MC->mangleCXXRTTIName(MC->getASTContext().getCanonicalTagType(D), NameStream);

428

429 return getBackendMangledName(Name);

430}

431

432std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {

434 raw_svector_ostream NameStream(Name);

435 MC->mangleCXXRTTI(MC->getASTContext().getCanonicalTagType(D), NameStream);

436

437 return getBackendMangledName(Name);

438}

439

440std::string

441InstallAPIVisitor::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

449std::string InstallAPIVisitor::getMangledCXXThunk(

450 const GlobalDecl &D, const ThunkInfo &Thunk, bool ElideOverrideInfo) const {

451 SmallString<256> Name;

452 raw_svector_ostream NameStream(Name);

454 if (const auto *Dtor = dyn_cast(Method))

455 MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk, ElideOverrideInfo,

456 NameStream);

457 else

458 MC->mangleThunk(Method, Thunk, ElideOverrideInfo, NameStream);

459

460 return getBackendMangledName(Name);

461}

462

463std::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(D))

470 else {

473 }

474 MC->mangleName(GD, NameStream);

475 return getBackendMangledName(Name);

476}

477

478void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,

479 const AvailabilityInfo &Avail,

481 bool EmittedVTable) {

483 EmittedVTable = true;

485 if (VTableLinkage == CXXLinkage::ExternalLinkage ||

486 VTableLinkage == CXXLinkage::WeakODRLinkage) {

487 const std::string Name = getMangledCXXVTableName(D);

488 const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;

489 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

490 GlobalRecord::Kind::Variable, Avail,

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) {

497 VTable->getThunkInfo(GD);

498 if (!Thunks)

499 return;

500

501 for (const auto &Thunk : *Thunks) {

502 const std::string Name =

503 getMangledCXXThunk(GD, Thunk, true);

504 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

505 GlobalRecord::Kind::Function,

506 Avail, GD.getDecl(), Access);

507 Ctx.Verifier->verify(GR, FA);

508 }

509 };

510

511 for (const auto *Method : D->methods()) {

513 continue;

514

515 if (auto Dtor = dyn_cast(Method)) {

516

517 if (Dtor->isDefaulted())

518 continue;

521 } else

523 }

524 }

525 }

526 }

527

528 if (!EmittedVTable)

529 return;

530

532 std::string Name = getMangledCXXRTTI(D);

533 auto [GR, FA] =

534 Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

535 GlobalRecord::Kind::Variable, Avail, D, Access);

536 Ctx.Verifier->verify(GR, FA);

537

538 Name = getMangledCXXRTTIName(D);

539 auto [NamedGR, NamedFA] =

540 Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

541 GlobalRecord::Kind::Variable, Avail, D, Access);

542 Ctx.Verifier->verify(NamedGR, NamedFA);

543 }

544

545 for (const auto &It : D->bases()) {

546 const auto *Base =

548 const auto BaseAccess = getAccessForDecl(Base);

549 if (!BaseAccess)

550 continue;

552 emitVTableSymbols(Base, BaseAvail, *BaseAccess, true);

553 }

554}

555

558 return true;

559

560

562 return true;

563

564

566 return true;

567

568 auto Access = getAccessForDecl(D);

569 if (!Access)

570 return true;

572

573

575 emitVTableSymbols(D, Avail, *Access);

576

578 bool KeepInlineAsWeak = false;

579 if (auto *Templ = dyn_cast(D)) {

580 ClassSK = Templ->getTemplateSpecializationKind();

582 KeepInlineAsWeak = true;

583 }

584

585

586 for (const auto *M : D->methods()) {

587

588

589 bool WeakDef = false;

591 if (!KeepInlineAsWeak)

592 continue;

593

594 WeakDef = true;

595 }

596

598 continue;

599

600 switch (M->getTemplateSpecializationKind()) {

603 break;

605 continue;

608 WeakDef = true;

609 break;

611 WeakDef = true;

612 break;

613 }

614

615 if (!M->isUserProvided())

616 continue;

617

618

619 if (M->isDeleted())

620 continue;

621

622 const auto Access = getAccessForDecl(M);

623 if (!Access)

624 return true;

626

627 if (const auto *Ctor = dyn_cast(M)) {

628

629 if (Ctor->isDefaulted())

630 continue;

631

632 std::string Name = getMangledCtorDtor(M, Ctor_Base);

633 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

634 GlobalRecord::Kind::Function, Avail,

635 D, *Access, getFlags(WeakDef));

636 Ctx.Verifier->verify(GR, FA);

637

639 std::string Name = getMangledCtorDtor(M, Ctor_Complete);

640 auto [GR, FA] = Ctx.Slice->addGlobal(

641 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,

642 D, *Access, getFlags(WeakDef));

643 Ctx.Verifier->verify(GR, FA);

644 }

645

646 continue;

647 }

648

649 if (const auto *Dtor = dyn_cast(M)) {

650

651 if (Dtor->isDefaulted())

652 continue;

653

654 std::string Name = getMangledCtorDtor(M, Dtor_Base);

655 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

656 GlobalRecord::Kind::Function, Avail,

657 D, *Access, getFlags(WeakDef));

658 Ctx.Verifier->verify(GR, FA);

659

661 auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal(

662 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D,

664 Ctx.Verifier->verify(CompleteGR, CompleteFA);

665

666 if (Dtor->isVirtual()) {

668 auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal(

669 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,

670 D, *Access, getFlags(WeakDef));

671 Ctx.Verifier->verify(VirtualGR, VirtualFA);

672 }

673

674 continue;

675 }

676

677

678

679

680 if (M->isPureVirtual())

681 continue;

682

683 std::string Name = getMangledName(M);

684 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

685 GlobalRecord::Kind::Function, Avail, M,

687 Ctx.Verifier->verify(GR, FA);

688 }

689

690 if (auto *Templ = dyn_cast(D)) {

691 if (!Templ->isExplicitInstantiationOrSpecialization())

692 return true;

693 }

694

696 using var_range = iterator_range<var_iter>;

697 for (const auto *Var : var_range(D->decls())) {

698

699

700

701

702

703

704 if (Var->isStaticDataMember() && Var->hasInit())

705 continue;

706

707

709 continue;

710

711 const std::string Name = getMangledName(Var);

712 const auto Access = getAccessForDecl(Var);

713 if (!Access)

714 return true;

716 const bool WeakDef = Var->hasAttr() || KeepInlineAsWeak;

717

718 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,

719 GlobalRecord::Kind::Variable, Avail, D,

721 Ctx.Verifier->verify(GR, FA);

722 }

723

724 return true;

725}

726

727}

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

TemplateOrSpecializationInfo getTemplateOrSpecializationInfo(const VarDecl *Var)

DynTypedNodeList getParents(const NodeT &Node)

Forwards to get node parents from the ParentMapContext.

const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)

Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...

const LangOptions & getLangOpts() const

DiagnosticsEngine & getDiagnostics() const

const TargetInfo & getTargetInfo() const

Represents a static or instance method of a struct/union/class.

Represents a C++ struct/union/class.

method_range methods() const

TemplateSpecializationKind getTemplateSpecializationKind() const

Determine whether this particular class is a specialization or instantiation of a class template or m...

bool isAbstract() const

Determine whether this class has a pure virtual function.

bool isDynamicClass() const

bool hasDefinition() const

ClassTemplateDecl * getDescribedClassTemplate() const

Retrieves the class template that is described by this class declaration.

specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

ASTContext & getASTContext() const LLVM_READONLY

bool isDefinedOutsideFunctionOrMethod() const

isDefinedOutsideFunctionOrMethod - This predicate returns true if this scoped decl is defined outside...

DeclContext * getDeclContext()

bool hasErrorOccurred() const

A dynamically typed AST node container.

Represents a function declaration or definition.

FunctionTemplateSpecializationInfo * getTemplateSpecializationInfo() const

If this function is actually a function template specialization, retrieve information about this func...

@ TK_MemberSpecialization

@ TK_DependentNonTemplate

@ TK_FunctionTemplateSpecialization

@ TK_DependentFunctionTemplateSpecialization

TemplatedKind getTemplatedKind() const

What kind of templated function this is.

redecl_range redecls() const

Returns an iterator range for all the redeclarations of the same decl.

TemplateSpecializationKind getTemplateSpecializationKind() const

Determine what kind of template instantiation this function represents.

clang::ObjCRuntime ObjCRuntime

This represents a decl that may have a name.

LinkageInfo getLinkageAndVisibility() const

Determines the linkage and visibility of this entity.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

Visibility getVisibility() const

Determines the visibility of this entity.

std::string getNameAsString() const

Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...

bool isExternallyVisible() const

ObjCCategoryDecl - Represents a category declaration.

ObjCInterfaceDecl * getClassInterface()

Represents an ObjC class declaration.

bool isThisDeclarationADefinition() const

Determine whether this particular declaration of this class is actually also a definition.

StringRef getObjCRuntimeNameAsString() const

Produce a name to be used for class's metadata.

ObjCInterfaceDecl * getSuperClass() const

The basic abstraction for the target Objective-C runtime.

bool isFragile() const

The inverse of isNonFragile(): does this runtime follow the set of implied behaviors for a "fragile" ...

bool TraverseDecl(Decl *D)

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

bool isMicrosoft() const

Is this ABI an MSVC-compatible ABI?

TargetCXXABI getCXXABI() const

Get the C++ ABI currently in use.

SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy

Represents a variable declaration or definition.

TLSKind getTLSKind() const

@ TLS_None

Not a TLS variable.

TemplateSpecializationKind getTemplateSpecializationKind() const

If this variable is an instantiation of a variable template or a static data member of a class templa...

void HandleTranslationUnit(ASTContext &ASTCtx) override

HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...

Definition Visitor.cpp:77

bool VisitCXXRecordDecl(const CXXRecordDecl *D)

Collect global c++ declarations.

Definition Visitor.cpp:556

bool VisitFunctionDecl(const FunctionDecl *D)

Collect global functions.

Definition Visitor.cpp:250

bool VisitVarDecl(const VarDecl *D)

Collect global variables.

Definition Visitor.cpp:215

bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D)

Collect Objective-C Category/Extension declarations.

Definition Visitor.cpp:197

bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D)

Collect Objective-C Interface declarations.

Definition Visitor.cpp:165

Defines the Linkage enumeration and various utility functions.

The DirectoryScanner for collecting library files on the file system.

static bool isInlined(const FunctionDecl *D)

Definition Visitor.cpp:42

static CXXLinkage getVTableLinkage(const CXXRecordDecl *D)

Definition Visitor.cpp:347

@ 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.

Definition Visitor.cpp:132

static bool hasVTable(const CXXRecordDecl *D)

Definition Visitor.cpp:303

static bool isRTTIWeakDef(const CXXRecordDecl *D)

Definition Visitor.cpp:387

static bool hasRTTI(const CXXRecordDecl *D)

Definition Visitor.cpp:400

static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal=false)

Definition Visitor.cpp:67

static bool isExported(const NamedDecl *D)

Definition Visitor.cpp:36

CXXCtorType

C++ constructor types.

@ Ctor_Base

Base object ctor.

@ Ctor_Complete

Complete object ctor.

bool isa(CodeGen::Address addr)

Linkage

Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.

@ Result

The result type of a method or function.

@ ExplicitInstantiation

We are parsing an explicit instantiation.

CXXDtorType

C++ destructor types.

@ Dtor_Base

Base object dtor.

@ Dtor_Complete

Complete object dtor.

@ Dtor_Deleting

Deleting dtor.

@ Type

The name was classified as a type.

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,...

U cast(CodeGen::Address addr)

@ 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::shared_ptr< FrontendRecordsSlice > Slice

Active TargetSlice for symbol record collection.

std::unique_ptr< DylibVerifier > Verifier

Verifier when binary dylib is passed as input.