[clang] [APINotes] Upstream APINotesManager (PR #72389)
Saleem Abdulrasool via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 15 08:08:22 PST 2023
================
@@ -0,0 +1,469 @@
+//===--- APINotesManager.cpp - Manage API Notes Files ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/APINotes/APINotesManager.h"
+#include "clang/APINotes/APINotesReader.h"
+#include "clang/APINotes/APINotesYAMLCompiler.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/SourceMgrAdapter.h"
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+
+using namespace clang;
+using namespace api_notes;
+
+#define DEBUG_TYPE "API Notes"
+STATISTIC(NumHeaderAPINotes, "non-framework API notes files loaded");
+STATISTIC(NumPublicFrameworkAPINotes, "framework public API notes loaded");
+STATISTIC(NumPrivateFrameworkAPINotes, "framework private API notes loaded");
+STATISTIC(NumFrameworksSearched, "frameworks searched");
+STATISTIC(NumDirectoriesSearched, "header directories searched");
+STATISTIC(NumDirectoryCacheHits, "directory cache hits");
+
+namespace {
+/// Prints two successive strings, which much be kept alive as long as the
+/// PrettyStackTrace entry.
+class PrettyStackTraceDoubleString : public llvm::PrettyStackTraceEntry {
+ StringRef First, Second;
+
+public:
+ PrettyStackTraceDoubleString(StringRef First, StringRef Second)
+ : First(First), Second(Second) {}
+ void print(raw_ostream &OS) const override { OS << First << Second; }
+};
+} // namespace
+
+APINotesManager::APINotesManager(SourceManager &SM, const LangOptions &LangOpts)
+ : SM(SM), ImplicitAPINotes(LangOpts.APINotes) {}
+
+APINotesManager::~APINotesManager() {
+ // Free the API notes readers.
+ for (const auto &Entry : Readers) {
+ if (auto Reader = Entry.second.dyn_cast<APINotesReader *>())
+ delete Reader;
+ }
+
+ delete CurrentModuleReaders[0];
+ delete CurrentModuleReaders[1];
+}
+
+std::unique_ptr<APINotesReader>
+APINotesManager::loadAPINotes(FileEntryRef APINotesFile) {
+ PrettyStackTraceDoubleString Trace("Loading API notes from ",
+ APINotesFile.getName());
+
+ // Open the source file.
+ auto SourceFileID = SM.getOrCreateFileID(APINotesFile, SrcMgr::C_User);
+ auto SourceBuffer = SM.getBufferOrNone(SourceFileID, SourceLocation());
+ if (!SourceBuffer)
+ return nullptr;
+
+ // Compile the API notes source into a buffer.
+ // FIXME: Either propagate OSType through or, better yet, improve the binary
+ // APINotes format to maintain complete availability information.
+ // FIXME: We don't even really need to go through the binary format at all;
+ // we're just going to immediately deserialize it again.
+ llvm::SmallVector<char, 1024> APINotesBuffer;
+ std::unique_ptr<llvm::MemoryBuffer> CompiledBuffer;
+ {
+ SourceMgrAdapter SMAdapter(
+ SM, SM.getDiagnostics(), diag::err_apinotes_message,
+ diag::warn_apinotes_message, diag::note_apinotes_message, APINotesFile);
+ llvm::raw_svector_ostream OS(APINotesBuffer);
+ if (api_notes::compileAPINotes(
+ SourceBuffer->getBuffer(), SM.getFileEntryForID(SourceFileID), OS,
+ SMAdapter.getDiagHandler(), SMAdapter.getDiagContext()))
+ return nullptr;
+
+ // Make a copy of the compiled form into the buffer.
+ CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+ StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+ }
+
+ // Load the binary form we just compiled.
+ auto Reader = APINotesReader::Create(std::move(CompiledBuffer), SwiftVersion);
+ assert(Reader && "Could not load the API notes we just generated?");
+ return Reader;
+}
+
+std::unique_ptr<APINotesReader>
+APINotesManager::loadAPINotes(StringRef Buffer) {
+ llvm::SmallVector<char, 1024> APINotesBuffer;
+ std::unique_ptr<llvm::MemoryBuffer> CompiledBuffer;
+ SourceMgrAdapter SMAdapter(
+ SM, SM.getDiagnostics(), diag::err_apinotes_message,
+ diag::warn_apinotes_message, diag::note_apinotes_message, std::nullopt);
+ llvm::raw_svector_ostream OS(APINotesBuffer);
+
+ if (api_notes::compileAPINotes(Buffer, nullptr, OS,
+ SMAdapter.getDiagHandler(),
+ SMAdapter.getDiagContext()))
+ return nullptr;
+
+ CompiledBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+ StringRef(APINotesBuffer.data(), APINotesBuffer.size()));
+ auto Reader = APINotesReader::Create(std::move(CompiledBuffer), SwiftVersion);
+ assert(Reader && "Could not load the API notes we just generated?");
+ return Reader;
+}
+
+bool APINotesManager::loadAPINotes(const DirectoryEntry *HeaderDir,
+ FileEntryRef APINotesFile) {
+ assert(Readers.find(HeaderDir) == Readers.end());
+ if (auto Reader = loadAPINotes(APINotesFile)) {
+ Readers[HeaderDir] = Reader.release();
+ return false;
+ }
+
+ Readers[HeaderDir] = nullptr;
+ return true;
+}
+
+OptionalFileEntryRef
+APINotesManager::findAPINotesFile(DirectoryEntryRef Directory,
+ StringRef Basename, bool WantPublic) {
+ FileManager &FM = SM.getFileManager();
+
+ llvm::SmallString<128> Path(Directory.getName());
+
+ StringRef BasenameSuffix = "";
+ if (!WantPublic)
+ BasenameSuffix = "_private";
----------------
compnerd wrote:
StringRef Suffix = WantPublic ? "" : "_private";
https://github.com/llvm/llvm-project/pull/72389
More information about the cfe-commits
mailing list