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::SymbolReference(const APIRecord *R) |
27 | : Name(R->Name), USR(R->USR), Record(R) {} |
28 | |
29 | APIRecord *APIRecord::castFromRecordContext(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::castToRecordContext(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::IsWellFormed() 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::stealRecordChain(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::addToRecordChain(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::findRecordForUSR(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::copyString(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::createSymbolReference(StringRef Name, StringRef USR, |
114 | StringRef Source) { |
115 | return SymbolReference(copyString(String: Name), copyString(String: USR), copyString(String: Source)); |
116 | } |
117 | |
118 | APIRecord::~APIRecord() {} |
119 | TagRecord::~TagRecord() {} |
120 | RecordRecord::~RecordRecord() {} |
121 | RecordFieldRecord::~RecordFieldRecord() {} |
122 | ObjCContainerRecord::~ObjCContainerRecord() {} |
123 | ObjCMethodRecord::~ObjCMethodRecord() {} |
124 | ObjCPropertyRecord::~ObjCPropertyRecord() {} |
125 | CXXMethodRecord::~CXXMethodRecord() {} |
126 | |
127 | void GlobalFunctionRecord::anchor() {} |
128 | void GlobalVariableRecord::anchor() {} |
129 | void EnumConstantRecord::anchor() {} |
130 | void EnumRecord::anchor() {} |
131 | void StructFieldRecord::anchor() {} |
132 | void StructRecord::anchor() {} |
133 | void UnionFieldRecord::anchor() {} |
134 | void UnionRecord::anchor() {} |
135 | void CXXFieldRecord::anchor() {} |
136 | void CXXClassRecord::anchor() {} |
137 | void CXXConstructorRecord::anchor() {} |
138 | void CXXDestructorRecord::anchor() {} |
139 | void CXXInstanceMethodRecord::anchor() {} |
140 | void CXXStaticMethodRecord::anchor() {} |
141 | void ObjCInstancePropertyRecord::anchor() {} |
142 | void ObjCClassPropertyRecord::anchor() {} |
143 | void ObjCInstanceVariableRecord::anchor() {} |
144 | void ObjCInstanceMethodRecord::anchor() {} |
145 | void ObjCClassMethodRecord::anchor() {} |
146 | void ObjCCategoryRecord::anchor() {} |
147 | void ObjCInterfaceRecord::anchor() {} |
148 | void ObjCProtocolRecord::anchor() {} |
149 | void MacroDefinitionRecord::anchor() {} |
150 | void TypedefRecord::anchor() {} |
151 |
Definitions
- SymbolReference
- castFromRecordContext
- castToRecordContext
- IsWellFormed
- stealRecordChain
- addToRecordChain
- findRecordForUSR
- copyString
- createSymbolReference
- ~APIRecord
- ~TagRecord
- ~RecordRecord
- ~RecordFieldRecord
- ~ObjCContainerRecord
- ~ObjCMethodRecord
- ~ObjCPropertyRecord
- ~CXXMethodRecord
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
- anchor
Learn to use CMake with our Intro Training
Find out more