clang  19.0.0git
Frontend.cpp
Go to the documentation of this file.
1 //===- Frontend.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 
10 #include "clang/AST/Availability.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/ADT/StringRef.h"
14 
15 using namespace llvm;
16 using namespace llvm::MachO;
17 
18 namespace clang::installapi {
19 std::pair<GlobalRecord *, FrontendAttrs *> FrontendRecordsSlice::addGlobal(
20  StringRef Name, RecordLinkage Linkage, GlobalRecord::Kind GV,
21  const clang::AvailabilityInfo Avail, const Decl *D, const HeaderType Access,
22  SymbolFlags Flags, bool Inlined) {
23 
24  GlobalRecord *GR =
25  llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags, Inlined);
26  auto Result = FrontendRecords.insert(
27  {GR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
28  return {GR, &(Result.first->second)};
29 }
30 
31 std::pair<ObjCInterfaceRecord *, FrontendAttrs *>
32 FrontendRecordsSlice::addObjCInterface(StringRef Name, RecordLinkage Linkage,
33  const clang::AvailabilityInfo Avail,
34  const Decl *D, HeaderType Access,
35  bool IsEHType) {
36  ObjCIFSymbolKind SymType =
37  ObjCIFSymbolKind::Class | ObjCIFSymbolKind::MetaClass;
38  if (IsEHType)
39  SymType |= ObjCIFSymbolKind::EHType;
40 
41  ObjCInterfaceRecord *ObjCR =
42  llvm::MachO::RecordsSlice::addObjCInterface(Name, Linkage, SymType);
43  auto Result = FrontendRecords.insert(
44  {ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
45  return {ObjCR, &(Result.first->second)};
46 }
47 
48 std::pair<ObjCCategoryRecord *, FrontendAttrs *>
49 FrontendRecordsSlice::addObjCCategory(StringRef ClassToExtend,
50  StringRef CategoryName,
51  const clang::AvailabilityInfo Avail,
52  const Decl *D, HeaderType Access) {
53  ObjCCategoryRecord *ObjCR =
54  llvm::MachO::RecordsSlice::addObjCCategory(ClassToExtend, CategoryName);
55  auto Result = FrontendRecords.insert(
56  {ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
57  return {ObjCR, &(Result.first->second)};
58 }
59 
60 std::pair<ObjCIVarRecord *, FrontendAttrs *> FrontendRecordsSlice::addObjCIVar(
61  ObjCContainerRecord *Container, StringRef IvarName, RecordLinkage Linkage,
62  const clang::AvailabilityInfo Avail, const Decl *D, HeaderType Access,
64  // If the decl otherwise would have been exported, check their access control.
65  // Ivar's linkage is also determined by this.
66  if ((Linkage == RecordLinkage::Exported) &&
67  ((AC == ObjCIvarDecl::Private) || (AC == ObjCIvarDecl::Package)))
68  Linkage = RecordLinkage::Internal;
69  ObjCIVarRecord *ObjCR =
70  llvm::MachO::RecordsSlice::addObjCIVar(Container, IvarName, Linkage);
71  auto Result = FrontendRecords.insert(
72  {ObjCR, FrontendAttrs{Avail, D, D->getLocation(), Access}});
73 
74  return {ObjCR, &(Result.first->second)};
75 }
76 
77 std::optional<HeaderType>
78 InstallAPIContext::findAndRecordFile(const FileEntry *FE,
79  const Preprocessor &PP) {
80  if (!FE)
81  return std::nullopt;
82 
83  // Check if header has been looked up already and whether it is something
84  // installapi should use.
85  auto It = KnownFiles.find(FE);
86  if (It != KnownFiles.end()) {
87  if (It->second != HeaderType::Unknown)
88  return It->second;
89  else
90  return std::nullopt;
91  }
92 
93  // If file was not found, search by how the header was
94  // included. This is primarily to resolve headers found
95  // in a different location than what passed directly as input.
96  StringRef IncludeName = PP.getHeaderSearchInfo().getIncludeNameForHeader(FE);
97  auto BackupIt = KnownIncludes.find(IncludeName.str());
98  if (BackupIt != KnownIncludes.end()) {
99  KnownFiles[FE] = BackupIt->second;
100  return BackupIt->second;
101  }
102 
103  // Record that the file was found to avoid future string searches for the
104  // same file.
105  KnownFiles.insert({FE, HeaderType::Unknown});
106  return std::nullopt;
107 }
108 
109 void InstallAPIContext::addKnownHeader(const HeaderFile &H) {
110  auto FE = FM->getFile(H.getPath());
111  if (!FE)
112  return; // File does not exist.
113  KnownFiles[*FE] = H.getType();
114 
115  if (!H.useIncludeName())
116  return;
117 
118  KnownIncludes[H.getIncludeName()] = H.getType();
119 }
120 
122  switch (Lang) {
123  default:
124  llvm_unreachable("Unexpected language option.");
125  case clang::Language::C:
126  return ".c";
128  return ".cpp";
130  return ".m";
132  return ".mm";
133  }
134 }
135 
136 std::unique_ptr<MemoryBuffer> createInputBuffer(InstallAPIContext &Ctx) {
137  assert(Ctx.Type != HeaderType::Unknown &&
138  "unexpected access level for parsing");
139  SmallString<4096> Contents;
140  raw_svector_ostream OS(Contents);
141  for (const HeaderFile &H : Ctx.InputHeaders) {
142  if (H.isExcluded())
143  continue;
144  if (H.getType() != Ctx.Type)
145  continue;
146  if (Ctx.LangMode == Language::C || Ctx.LangMode == Language::CXX)
147  OS << "#include ";
148  else
149  OS << "#import ";
150  if (H.useIncludeName())
151  OS << "<" << H.getIncludeName() << ">\n";
152  else
153  OS << "\"" << H.getPath() << "\"\n";
154 
155  Ctx.addKnownHeader(H);
156  }
157  if (Contents.empty())
158  return nullptr;
159 
160  SmallString<64> BufferName(
161  {"installapi-includes-", Ctx.Slice->getTriple().str(), "-",
162  getName(Ctx.Type), getFileExtension(Ctx.LangMode)});
163  return llvm::MemoryBuffer::getMemBufferCopy(Contents, BufferName);
164 }
165 
166 std::string findLibrary(StringRef InstallName, FileManager &FM,
167  ArrayRef<std::string> FrameworkSearchPaths,
168  ArrayRef<std::string> LibrarySearchPaths,
169  ArrayRef<std::string> SearchPaths) {
170  auto getLibrary =
171  [&](const StringRef FullPath) -> std::optional<std::string> {
172  // Prefer TextAPI files when possible.
173  SmallString<PATH_MAX> TextAPIFilePath = FullPath;
174  replace_extension(TextAPIFilePath, ".tbd");
175 
176  if (FM.getOptionalFileRef(TextAPIFilePath))
177  return std::string(TextAPIFilePath);
178 
179  if (FM.getOptionalFileRef(FullPath))
180  return std::string(FullPath);
181 
182  return std::nullopt;
183  };
184 
185  const StringRef Filename = sys::path::filename(InstallName);
186  const bool IsFramework = sys::path::parent_path(InstallName)
187  .ends_with((Filename + ".framework").str());
188  if (IsFramework) {
189  for (const StringRef Path : FrameworkSearchPaths) {
190  SmallString<PATH_MAX> FullPath(Path);
191  sys::path::append(FullPath, Filename + StringRef(".framework"), Filename);
192  if (auto LibOrNull = getLibrary(FullPath))
193  return *LibOrNull;
194  }
195  } else {
196  // Copy Apple's linker behavior: If this is a .dylib inside a framework, do
197  // not search -L paths.
198  bool IsEmbeddedDylib = (sys::path::extension(InstallName) == ".dylib") &&
199  InstallName.contains(".framework/");
200  if (!IsEmbeddedDylib) {
201  for (const StringRef Path : LibrarySearchPaths) {
202  SmallString<PATH_MAX> FullPath(Path);
203  sys::path::append(FullPath, Filename);
204  if (auto LibOrNull = getLibrary(FullPath))
205  return *LibOrNull;
206  }
207  }
208  }
209 
210  for (const StringRef Path : SearchPaths) {
211  SmallString<PATH_MAX> FullPath(Path);
212  sys::path::append(FullPath, InstallName);
213  if (auto LibOrNull = getLibrary(FullPath))
214  return *LibOrNull;
215  }
216 
217  return {};
218 }
219 
220 } // namespace clang::installapi
StringRef Filename
Definition: Format.cpp:2976
llvm::MachO::ObjCIVarRecord ObjCIVarRecord
Definition: MachO.h:37
llvm::MachO::SymbolFlags SymbolFlags
Definition: MachO.h:29
llvm::MachO::ObjCCategoryRecord ObjCCategoryRecord
Definition: MachO.h:36
llvm::MachO::GlobalRecord GlobalRecord
Definition: MachO.h:33
llvm::MachO::ObjCInterfaceRecord ObjCInterfaceRecord
Definition: MachO.h:35
llvm::MachO::ObjCIFSymbolKind ObjCIFSymbolKind
Definition: MachO.h:38
llvm::MachO::RecordLinkage RecordLinkage
Definition: MachO.h:30
llvm::MachO::ObjCContainerRecord ObjCContainerRecord
Definition: MachO.h:34
static std::string getName(const CallEvent &Call)
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getLocation() const
Definition: DeclBase.h:445
Cached information about one file (either on disk or in the virtual file system).
Definition: FileEntry.h:300
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
Definition: FileManager.h:240
StringRef getIncludeNameForHeader(const FileEntry *File) const
Retrieve the include name for the header.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:128
HeaderSearch & getHeaderSearchInfo() const
HeaderType getType() const
Definition: HeaderFile.h:78
StringRef getIncludeName() const
Definition: HeaderFile.h:79
StringRef getPath() const
Definition: HeaderFile.h:80
Representations of a library's headers for InstallAPI.
Definition: Context.h:20
std::unique_ptr< llvm::MemoryBuffer > createInputBuffer(InstallAPIContext &Ctx)
Create a buffer that contains all headers to scan for global symbols with.
Definition: Frontend.cpp:136
static StringRef getFileExtension(clang::Language Lang)
Definition: Frontend.cpp:121
std::string findLibrary(StringRef InstallName, FileManager &FM, ArrayRef< std::string > FrameworkSearchPaths, ArrayRef< std::string > LibrarySearchPaths, ArrayRef< std::string > SearchPaths)
Lookup the dylib or TextAPI file location for a system library or framework.
Definition: Frontend.cpp:166
Linkage
Describes the different kinds of linkage (C++ [basic.link], C99 6.2.2) that an entity may have.
Definition: Linkage.h:24
Language
The language for the input, used to select and validate the language standard and possible actions.
Definition: LangStandard.h:23
@ C
Languages that the frontend can parse and compile.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
Storage of availability attributes for a declaration.
Definition: Availability.h:64
Frontend information captured about records.
Struct used for generating validating InstallAPI.
Definition: Context.h:26
void addKnownHeader(const HeaderFile &H)
Populate entries of headers that should be included for TextAPI generation.
Definition: Frontend.cpp:109
HeaderType Type
Active header access type.
Definition: Context.h:41
std::shared_ptr< FrontendRecordsSlice > Slice
Active TargetSlice for symbol record collection.
Definition: Context.h:44
Language LangMode
Active language mode to parse in.
Definition: Context.h:38
HeaderSeq InputHeaders
All headers that represent a library.
Definition: Context.h:35