clang 20.0.0git
API.cpp
Go to the documentation of this file.
1//===- ExtractAPI/API.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/// \file
10/// This file implements the APIRecord and derived record structs,
11/// and the APISet class.
12///
13//===----------------------------------------------------------------------===//
14
16#include "llvm/ADT/StringRef.h"
17#include "llvm/Support/ErrorHandling.h"
18#include <memory>
19
20using namespace clang::extractapi;
21using namespace llvm;
22
24 : Name(R->Name), USR(R->USR), Record(R) {}
25
27 switch (Ctx->getKind()) {
28#define RECORD_CONTEXT(CLASS, KIND) \
29 case KIND: \
30 return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
32 default:
33 return nullptr;
34 // llvm_unreachable("RecordContext derived class isn't propertly
35 // implemented");
36 }
37}
38
40 if (!Record)
41 return nullptr;
42 switch (Record->getKind()) {
43#define RECORD_CONTEXT(CLASS, KIND) \
44 case KIND: \
45 return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
47 default:
48 return nullptr;
49 // llvm_unreachable("RecordContext derived class isn't propertly
50 // implemented");
51 }
52}
53
54bool RecordContext::IsWellFormed() const {
55 // Check that First and Last are both null or both non-null.
56 return (First == nullptr) == (Last == nullptr);
57}
58
60 assert(IsWellFormed());
61 // Other's record chain is empty, nothing to do
62 if (Other.First == nullptr && Other.Last == nullptr)
63 return;
64
65 // If we don't have an empty chain append Other's chain into ours.
66 if (First)
67 Last->NextInContext = Other.First;
68 else
69 First = Other.First;
70
71 Last = Other.Last;
72
73 for (auto *StolenRecord = Other.First; StolenRecord != nullptr;
74 StolenRecord = StolenRecord->getNextInContext())
75 StolenRecord->Parent = SymbolReference(cast<APIRecord>(this));
76
77 // Delete Other's chain to ensure we don't accidentally traverse it.
78 Other.First = nullptr;
79 Other.Last = nullptr;
80}
81
83 assert(IsWellFormed());
84 if (!First) {
85 First = Record;
86 Last = Record;
87 return;
88 }
89
90 Last->NextInContext = Record;
91 Last = Record;
92}
93
95 APIRecord *Prev = nullptr;
96 for (APIRecord *Curr = First; Curr != Record; Curr = Curr->NextInContext)
97 Prev = Curr;
98
99 if (Prev)
100 Prev->NextInContext = Record->NextInContext;
101 else
102 First = Record->NextInContext;
103
104 if (Last == Record)
105 Last = Prev;
106
107 Record->NextInContext = nullptr;
108}
109
110APIRecord *APISet::findRecordForUSR(StringRef USR) const {
111 if (USR.empty())
112 return nullptr;
113
114 auto FindIt = USRBasedLookupTable.find(USR);
115 if (FindIt != USRBasedLookupTable.end())
116 return FindIt->getSecond().get();
117
118 return nullptr;
119}
120
121StringRef APISet::copyString(StringRef String) {
122 if (String.empty())
123 return {};
124
125 // No need to allocate memory and copy if the string has already been stored.
126 if (Allocator.identifyObject(String.data()))
127 return String;
128
129 void *Ptr = Allocator.Allocate(String.size(), 1);
130 memcpy(Ptr, String.data(), String.size());
131 return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
132}
133
134SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
135 StringRef Source) {
136 return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
137}
138
139void APISet::removeRecord(StringRef USR) {
140 auto Result = USRBasedLookupTable.find(USR);
141 if (Result != USRBasedLookupTable.end()) {
142 auto *Record = Result->getSecond().get();
143 auto &ParentReference = Record->Parent;
144 auto *ParentRecord = const_cast<APIRecord *>(ParentReference.Record);
145 if (!ParentRecord)
146 ParentRecord = findRecordForUSR(ParentReference.USR);
147
148 if (auto *ParentCtx = llvm::cast_if_present<RecordContext>(ParentRecord)) {
149 ParentCtx->removeFromRecordChain(Record);
150 if (auto *RecordAsCtx = llvm::dyn_cast<RecordContext>(Record))
151 ParentCtx->stealRecordChain(*RecordAsCtx);
152 } else {
153 TopLevelRecords.erase(Record);
154 if (auto *RecordAsCtx = llvm::dyn_cast<RecordContext>(Record)) {
155 for (const auto *Child = RecordAsCtx->First; Child != nullptr;
156 Child = Child->getNextInContext())
157 TopLevelRecords.insert(Child);
158 }
159 }
160 USRBasedLookupTable.erase(Result);
161 }
162}
163
165
170ObjCContainerRecord::~ObjCContainerRecord() {}
174
175void GlobalFunctionRecord::anchor() {}
176void GlobalVariableRecord::anchor() {}
177void EnumConstantRecord::anchor() {}
178void EnumRecord::anchor() {}
179void StructFieldRecord::anchor() {}
180void StructRecord::anchor() {}
181void UnionFieldRecord::anchor() {}
182void UnionRecord::anchor() {}
183void CXXFieldRecord::anchor() {}
184void CXXClassRecord::anchor() {}
185void CXXConstructorRecord::anchor() {}
186void CXXDestructorRecord::anchor() {}
187void CXXInstanceMethodRecord::anchor() {}
188void CXXStaticMethodRecord::anchor() {}
189void ObjCInstancePropertyRecord::anchor() {}
190void ObjCClassPropertyRecord::anchor() {}
191void ObjCInstanceVariableRecord::anchor() {}
192void ObjCInstanceMethodRecord::anchor() {}
193void ObjCClassMethodRecord::anchor() {}
194void ObjCCategoryRecord::anchor() {}
195void ObjCInterfaceRecord::anchor() {}
196void ObjCProtocolRecord::anchor() {}
197void MacroDefinitionRecord::anchor() {}
198void TypedefRecord::anchor() {}
This file defines the APIRecord-based structs and the APISet class.
llvm::MachO::Record Record
Definition: MachO.h:31
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
SymbolReference createSymbolReference(StringRef Name, StringRef USR, StringRef Source="")
Definition: API.cpp:134
StringRef copyString(StringRef String)
Copy String into the Allocator in this APISet.
Definition: API.cpp:121
void removeRecord(StringRef USR)
Definition: API.cpp:139
APIRecord * findRecordForUSR(StringRef USR) const
Finds the APIRecord for a given USR.
Definition: API.cpp:110
Base class used for specific record types that have children records this is analogous to the DeclCon...
Definition: API.h:305
void removeFromRecordChain(APIRecord *Record)
Definition: API.cpp:94
APIRecord::RecordKind getKind() const
Definition: API.h:325
void stealRecordChain(RecordContext &Other)
Append Other children chain into ours and empty out Other's record chain.
Definition: API.cpp:59
void addToRecordChain(APIRecord *) const
Definition: API.cpp:82
@ Result
The result type of a method or function.
@ Other
Other implicit parameter.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
The base representation of an API record. Holds common symbol information.
Definition: API.h:184
virtual ~APIRecord()=0
Definition: API.cpp:166
static APIRecord * castFromRecordContext(const RecordContext *Ctx)
Definition: API.cpp:26
static RecordContext * castToRecordContext(const APIRecord *Record)
Definition: API.cpp:39
virtual ~TagRecord()=0
Definition: API.cpp:167