clang: lib/InstallAPI/Visitor.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
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
21using namespace llvm;
23
24namespace {
25enum class CXXLinkage {
26 ExternalLinkage,
27 LinkOnceODRLinkage,
28 WeakODRLinkage,
29 PrivateLinkage,
30};
31}
32
34
35
36
38 auto LV = D->getLinkageAndVisibility();
41}
42
44 bool HasInlineAttribute = false;
45 bool NoCXXAttr =
46 (->getASTContext().getLangOpts().CPlusPlus &&
47 ->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
48 ->hasAttr());
49
50
51 for (const auto *RD : D->redecls()) {
52 if (!RD->isInlined())
53 continue;
54 HasInlineAttribute = true;
55 if (!(NoCXXAttr || RD->hasAttr()))
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
70 if (WeakDef)
71 Result |= SymbolFlags::WeakDefined;
72 if (ThreadLocal)
73 Result |= SymbolFlags::ThreadLocalValue;
74
76}
77
80 return;
81
84}
85
86std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
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
97std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
99 Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
100 return std::string(FinalName);
101}
102
103std::optional
104InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {
105 SourceLocation Loc = D->getLocation();
106 if (Loc.isInvalid())
107 return std::nullopt;
108
109
110
113 if (ID.isInvalid())
114 return std::nullopt;
115
117 if (!FE)
118 return std::nullopt;
119
121 if (!Header.has_value())
122 return std::nullopt;
123
125 assert(Access != HeaderType::Unknown && "unexpected access level for global");
126 return Access;
127}
128
129
130
131
132
134 for (; D != nullptr; D = D->getSuperClass())
135 if (D->hasAttr())
136 return true;
137
138 return false;
139}
140void InstallAPIVisitor::recordObjCInstanceVariables(
142 const llvm::iterator_range<
144 Ivars) {
147
149 Linkage = RecordLinkage::Unknown;
150
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();
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
167
168 if (->isThisDeclarationADefinition())
169 return true;
170
171
172 auto Access = getAccessForDecl(D);
173 if (!Access)
174 return true;
175
176 StringRef Name = D->getObjCRuntimeNameAsString();
178 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
180 const bool IsEHType =
181 (->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
183
184 auto [Class, FA] =
185 Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
187
188
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
199 StringRef CategoryName = D->getName();
200
201 auto Access = getAccessForDecl(D);
202 if (!Access)
203 return true;
206 const StringRef InterfaceName = InterfaceD->getName();
207
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
217
218 if (isa(D))
219 return true;
220
221
222 if (D->getDeclContext()->isRecord())
223 return true;
224
225
226 if (->isDefinedOutsideFunctionOrMethod())
227 return true;
228
229
230 if (D->getASTContext().getTemplateOrSpecializationInfo(D) &&
232 return true;
233
234
235 auto Access = getAccessForDecl(D);
236 if (!Access)
237 return true;
238
240 isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
241 const bool WeakDef = D->hasAttr();
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
252 if (const CXXMethodDecl *M = dyn_cast(D)) {
253
254 if (M->getParent()->getDescribedClassTemplate() != nullptr)
255 return true;
256
257
258 for (const DynTypedNode &P : D->getASTContext().getParents(*M)) {
260 return true;
261 }
262
263
264 if (isa(M) || isa(M))
265 return true;
266 }
267
268
269 switch (D->getTemplatedKind()) {
272 break;
275 if (auto *TempInfo = D->getTemplateSpecializationInfo()) {
276 if (!TempInfo->isExplicitInstantiationOrSpecialization())
277 return true;
278 }
279 break;
282 return true;
283 }
284
285 auto Access = getAccessForDecl(D);
286 if (!Access)
287 return true;
288 auto Name = getMangledName(D);
290 const bool ExplicitInstantiation = D->getTemplateSpecializationKind() ==
292 const bool WeakDef = ExplicitInstantiation || D->hasAttr();
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
305
306
307 if (->hasDefinition() ||
->isDynamicClass())
308 return false;
309
310 assert(D->isExternallyVisible() && "Should be externally visible");
311 assert(D->isCompleteDefinition() && "Only works on complete definitions");
312
314 D->getASTContext().getCurrentKeyFunction(D);
315
316
317 if (KeyFunctionD) {
323 return true;
325 llvm_unreachable(
326 "Unexpected TemplateSpecializationKind for key function");
327 }
328 } else if (D->isAbstract()) {
329
330
331 return false;
332 }
333
334 switch (D->getTemplateSpecializationKind()) {
338 return false;
339
342 return true;
343 }
344
345 llvm_unreachable("Invalid TemplateSpecializationKind!");
346}
347
349 assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable");
350 assert(D->isExternallyVisible() && "Record should be externally visible");
352 return CXXLinkage::PrivateLinkage;
353
355 D->getASTContext().getCurrentKeyFunction(D);
356 if (KeyFunctionD) {
357
358
363 return CXXLinkage::LinkOnceODRLinkage;
364 return CXXLinkage::ExternalLinkage;
366 llvm_unreachable("No external vtable for implicit instantiations");
368 return CXXLinkage::WeakODRLinkage;
370 llvm_unreachable(
371 "Unexpected TemplateSpecializationKind for key function");
372 }
373 }
374
375 switch (D->getTemplateSpecializationKind()) {
379 return CXXLinkage::LinkOnceODRLinkage;
382 return CXXLinkage::WeakODRLinkage;
383 }
384
385 llvm_unreachable("Invalid TemplateSpecializationKind!");
386}
387
389 if (D->hasAttr())
390 return true;
391
392 if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr)
393 return true;
394
395 if (D->isDynamicClass())
397
398 return false;
399}
400
402 if (->getASTContext().getLangOpts().RTTI)
403 return false;
404
405 if (->hasDefinition())
406 return false;
407
408 if (->isDynamicClass())
409 return false;
410
411
412
413
414
415
416
417
419 return false;
420
421 return true;
422}
423
424std::string
425InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
427 raw_svector_ostream NameStream(Name);
428 MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream);
429
430 return getBackendMangledName(Name);
431}
432
433std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
435 raw_svector_ostream NameStream(Name);
436 MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream);
437
438 return getBackendMangledName(Name);
439}
440
441std::string
442InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const {
444 raw_svector_ostream NameStream(Name);
445 MC->mangleCXXVTable(D, NameStream);
446
447 return getBackendMangledName(Name);
448}
449
450std::string InstallAPIVisitor::getMangledCXXThunk(
451 const GlobalDecl &D, const ThunkInfo &Thunk, bool ElideOverrideInfo) const {
453 raw_svector_ostream NameStream(Name);
454 const auto *Method = cast(D.getDecl());
455 if (const auto *Dtor = dyn_cast(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
464std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D,
465 int Type) const {
467 raw_svector_ostream NameStream(Name);
468 GlobalDecl GD;
469 if (const auto *Ctor = dyn_cast(D))
470 GD = GlobalDecl(Ctor, CXXCtorType(Type));
471 else {
472 const auto *Dtor = cast(D);
473 GD = GlobalDecl(Dtor, CXXDtorType(Type));
474 }
475 MC->mangleName(GD, NameStream);
476 return getBackendMangledName(Name);
477}
478
479void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
480 const AvailabilityInfo &Avail,
482 bool EmittedVTable) {
484 EmittedVTable = true;
486 if (VTableLinkage == CXXLinkage::ExternalLinkage ||
487 VTableLinkage == CXXLinkage::WeakODRLinkage) {
488 const std::string Name = getMangledCXXVTableName(D);
489 const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;
490 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
491 GlobalRecord::Kind::Variable, Avail,
493 Ctx.Verifier->verify(GR, FA);
494 if (->getDescribedClassTemplate() &&
->isInvalidDecl()) {
495 VTableContextBase *VTable = D->getASTContext().getVTableContext();
496 auto AddThunk = [&](GlobalDecl GD) {
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, 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(Method) || !Method->isVirtual())
514 continue;
515
516 if (auto Dtor = dyn_cast(Method)) {
517
518 if (Dtor->isDefaulted())
519 continue;
522 } else
523 AddThunk(Method);
524 }
525 }
526 }
527 }
528
529 if (!EmittedVTable)
530 return;
531
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(It.getType()->castAs()->getDecl());
549 const auto BaseAccess = getAccessForDecl(Base);
550 if (!BaseAccess)
551 continue;
553 emitVTableSymbols(Base, BaseAvail, *BaseAccess, true);
554 }
555}
556
558 if (->isCompleteDefinition())
559 return true;
560
561
562 if (D->getDescribedClassTemplate() != nullptr)
563 return true;
564
565
566 if (isa(D))
567 return true;
568
569 auto Access = getAccessForDecl(D);
570 if (!Access)
571 return true;
573
574
576 emitVTableSymbols(D, Avail, *Access);
577
579 bool KeepInlineAsWeak = false;
580 if (auto *Templ = dyn_cast(D)) {
581 ClassSK = Templ->getTemplateSpecializationKind();
583 KeepInlineAsWeak = true;
584 }
585
586
587 for (const auto *M : D->methods()) {
588
589
590 bool WeakDef = false;
592 if (!KeepInlineAsWeak)
593 continue;
594
595 WeakDef = true;
596 }
597
599 continue;
600
601 switch (M->getTemplateSpecializationKind()) {
604 break;
606 continue;
609 WeakDef = true;
610 break;
612 WeakDef = true;
613 break;
614 }
615
616 if (!M->isUserProvided())
617 continue;
618
619
620 if (M->isDeleted())
621 continue;
622
623 const auto Access = getAccessForDecl(M);
624 if (!Access)
625 return true;
627
628 if (const auto *Ctor = dyn_cast(M)) {
629
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,
637 Ctx.Verifier->verify(GR, FA);
638
639 if (->isAbstract()) {
640 std::string Name = getMangledCtorDtor(M, Ctor_Complete);
641 auto [GR, FA] = Ctx.Slice->addGlobal(
642 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
644 Ctx.Verifier->verify(GR, FA);
645 }
646
647 continue;
648 }
649
650 if (const auto *Dtor = dyn_cast(M)) {
651
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,
659 Ctx.Verifier->verify(GR, FA);
660
662 auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal(
663 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D,
665 Ctx.Verifier->verify(CompleteGR, CompleteFA);
666
667 if (Dtor->isVirtual()) {
669 auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal(
670 Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail,
672 Ctx.Verifier->verify(VirtualGR, VirtualFA);
673 }
674
675 continue;
676 }
677
678
679
680
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,
688 Ctx.Verifier->verify(GR, FA);
689 }
690
691 if (auto *Templ = dyn_cast(D)) {
692 if (!Templ->isExplicitInstantiationOrSpecialization())
693 return true;
694 }
695
697 using var_range = iterator_range<var_iter>;
698 for (const auto *Var : var_range(D->decls())) {
699
700
701
702
703
704
705 if (Var->isStaticDataMember() && Var->hasInit())
706 continue;
707
708
710 continue;
711
712 const std::string Name = getMangledName(Var);
713 const auto Access = getAccessForDecl(Var);
714 if (!Access)
715 return true;
717 const bool WeakDef = Var->hasAttr() || KeepInlineAsWeak;
718
719 auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
720 GlobalRecord::Kind::Variable, Avail, D,
722 Ctx.Verifier->verify(GR, FA);
723 }
724
725 return true;
726}
727
728}
llvm::MachO::SymbolFlags SymbolFlags
llvm::MachO::ObjCCategoryRecord ObjCCategoryRecord
llvm::MachO::RecordLinkage RecordLinkage
llvm::MachO::Record Record
llvm::MachO::ObjCContainerRecord ObjCContainerRecord
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
Represents a static or instance method of a struct/union/class.
Represents a C++ struct/union/class.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
bool hasErrorOccurred() const
A dynamically typed AST node container.
Represents a function declaration or definition.
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
@ TK_DependentFunctionTemplateSpecialization
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
clang::ObjCRuntime ObjCRuntime
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
ObjCCategoryDecl - Represents a category declaration.
Represents an ObjC class declaration.
bool isFragile() const
The inverse of isNonFragile(): does this runtime follow the set of implied behaviors for a "fragile" ...
A (possibly-)qualified type.
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getFileLoc(SourceLocation Loc) const
Given Loc, if it is a macro location return the expansion location or the spelling location,...
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
Represents a variable declaration or definition.
@ TLS_None
Not a TLS variable.
void HandleTranslationUnit(ASTContext &ASTCtx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
bool VisitCXXRecordDecl(const CXXRecordDecl *D)
Collect global c++ declarations.
bool VisitFunctionDecl(const FunctionDecl *D)
Collect global functions.
bool VisitVarDecl(const VarDecl *D)
Collect global variables.
bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D)
Collect Objective-C Category/Extension declarations.
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D)
Collect Objective-C Interface declarations.
Defines the Linkage enumeration and various utility functions.
The DirectoryScanner for collecting library files on the file system.
static bool isInlined(const FunctionDecl *D)
static CXXLinkage getVTableLinkage(const CXXRecordDecl *D)
@ Unknown
Unset or unknown type.
static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D)
Check if the interface itself or any of its super classes have an exception attribute.
static bool hasVTable(const CXXRecordDecl *D)
static bool isRTTIWeakDef(const CXXRecordDecl *D)
static bool hasRTTI(const CXXRecordDecl *D)
static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal=false)
static bool isExported(const NamedDecl *D)
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
@ Result
The result type of a method or function.
CXXDtorType
C++ destructor types.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
@ Class
The "class" keyword introduces the elaborated-type-specifier.
bool isExternallyVisible(Linkage L)
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
@ DefaultVisibility
Objects with "default" visibility are seen by the dynamic linker and act like normal objects.
Diagnostic wrappers for TextAPI types for error reporting.
Storage of availability attributes for a declaration.
static AvailabilityInfo createFromDecl(const Decl *Decl)
std::optional< HeaderType > findAndRecordFile(const FileEntry *FE, const Preprocessor &PP)
Record visited files during frontend actions to determine whether to include their declarations for T...
std::shared_ptr< FrontendRecordsSlice > Slice
Active TargetSlice for symbol record collection.
std::unique_ptr< DylibVerifier > Verifier
Verifier when binary dylib is passed as input.