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