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 | |
15 | #include "clang/ExtractAPI/API.h" |
16 | #include "clang/AST/RawCommentList.h" |
17 | #include "clang/Index/USRGeneration.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/Support/ErrorHandling.h" |
20 | #include <memory> |
21 | |
22 | using namespace clang::extractapi; |
23 | using namespace llvm; |
24 | |
25 | SymbolReference::(const APIRecord *R) |
26 | : Name(R->Name), USR(R->USR), Record(R) {} |
27 | |
28 | APIRecord *APIRecord::(const RecordContext *Ctx) { |
29 | switch (Ctx->getKind()) { |
30 | #define RECORD_CONTEXT(CLASS, KIND) \ |
31 | case KIND: \ |
32 | return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx)); |
33 | #include "clang/ExtractAPI/APIRecords.inc" |
34 | default: |
35 | return nullptr; |
36 | // llvm_unreachable("RecordContext derived class isn't propertly |
37 | // implemented"); |
38 | } |
39 | } |
40 | |
41 | RecordContext *APIRecord::(const APIRecord *Record) { |
42 | if (!Record) |
43 | return nullptr; |
44 | switch (Record->getKind()) { |
45 | #define RECORD_CONTEXT(CLASS, KIND) \ |
46 | case KIND: \ |
47 | return static_cast<CLASS *>(const_cast<APIRecord *>(Record)); |
48 | #include "clang/ExtractAPI/APIRecords.inc" |
49 | default: |
50 | return nullptr; |
51 | // llvm_unreachable("RecordContext derived class isn't propertly |
52 | // implemented"); |
53 | } |
54 | } |
55 | |
56 | bool RecordContext::() const { |
57 | // Check that First and Last are both null or both non-null. |
58 | return (First == nullptr) == (Last == nullptr); |
59 | } |
60 | |
61 | void RecordContext::(RecordContext &Other) { |
62 | assert(IsWellFormed()); |
63 | // If we don't have an empty chain append Other's chain into ours. |
64 | if (First) |
65 | Last->NextInContext = Other.First; |
66 | else |
67 | First = Other.First; |
68 | |
69 | Last = Other.Last; |
70 | |
71 | // Delete Other's chain to ensure we don't accidentally traverse it. |
72 | Other.First = nullptr; |
73 | Other.Last = nullptr; |
74 | } |
75 | |
76 | void RecordContext::(APIRecord *Record) const { |
77 | assert(IsWellFormed()); |
78 | if (!First) { |
79 | First = Record; |
80 | Last = Record; |
81 | return; |
82 | } |
83 | |
84 | Last->NextInContext = Record; |
85 | Last = Record; |
86 | } |
87 | |
88 | APIRecord *APISet::(StringRef USR) const { |
89 | if (USR.empty()) |
90 | return nullptr; |
91 | |
92 | auto FindIt = USRBasedLookupTable.find(Val: USR); |
93 | if (FindIt != USRBasedLookupTable.end()) |
94 | return FindIt->getSecond().get(); |
95 | |
96 | return nullptr; |
97 | } |
98 | |
99 | StringRef APISet::(StringRef String) { |
100 | if (String.empty()) |
101 | return {}; |
102 | |
103 | // No need to allocate memory and copy if the string has already been stored. |
104 | if (Allocator.identifyObject(Ptr: String.data())) |
105 | return String; |
106 | |
107 | void *Ptr = Allocator.Allocate(Size: String.size(), Alignment: 1); |
108 | memcpy(dest: Ptr, src: String.data(), n: String.size()); |
109 | return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); |
110 | } |
111 | |
112 | SymbolReference APISet::(StringRef Name, StringRef USR, |
113 | StringRef Source) { |
114 | return SymbolReference(copyString(String: Name), copyString(String: USR), copyString(String: Source)); |
115 | } |
116 | |
117 | APIRecord::() {} |
118 | TagRecord::() {} |
119 | RecordRecord::() {} |
120 | RecordFieldRecord::() {} |
121 | ObjCContainerRecord::() {} |
122 | ObjCMethodRecord::() {} |
123 | ObjCPropertyRecord::() {} |
124 | CXXMethodRecord::() {} |
125 | |
126 | void GlobalFunctionRecord::() {} |
127 | void GlobalVariableRecord::() {} |
128 | void EnumConstantRecord::() {} |
129 | void EnumRecord::() {} |
130 | void StructFieldRecord::() {} |
131 | void StructRecord::() {} |
132 | void UnionFieldRecord::() {} |
133 | void UnionRecord::() {} |
134 | void CXXFieldRecord::() {} |
135 | void CXXClassRecord::() {} |
136 | void CXXConstructorRecord::() {} |
137 | void CXXDestructorRecord::() {} |
138 | void CXXInstanceMethodRecord::() {} |
139 | void CXXStaticMethodRecord::() {} |
140 | void ObjCInstancePropertyRecord::() {} |
141 | void ObjCClassPropertyRecord::() {} |
142 | void ObjCInstanceVariableRecord::() {} |
143 | void ObjCInstanceMethodRecord::() {} |
144 | void ObjCClassMethodRecord::() {} |
145 | void ObjCCategoryRecord::() {} |
146 | void ObjCInterfaceRecord::() {} |
147 | void ObjCProtocolRecord::() {} |
148 | void MacroDefinitionRecord::() {} |
149 | void TypedefRecord::() {} |
150 | |