xref: /freebsd/contrib/llvm-project/clang/lib/ExtractAPI/API.cpp (revision 24d5a8e6eec2b9eed9591971f223d79b8d7044c9)
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::SymbolReference(const APIRecord *R)
26      : Name(R->Name), USR(R->USR), Record(R) {}
27  
28  APIRecord *APIRecord::castFromRecordContext(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::castToRecordContext(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::IsWellFormed() 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::stealRecordChain(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::addToRecordChain(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::findRecordForUSR(StringRef USR) const {
89    if (USR.empty())
90      return nullptr;
91  
92    auto FindIt = USRBasedLookupTable.find(USR);
93    if (FindIt != USRBasedLookupTable.end())
94      return FindIt->getSecond().get();
95  
96    return nullptr;
97  }
98  
99  StringRef APISet::copyString(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(String.data()))
105      return String;
106  
107    void *Ptr = Allocator.Allocate(String.size(), 1);
108    memcpy(Ptr, String.data(), String.size());
109    return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
110  }
111  
112  SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
113                                                StringRef Source) {
114    return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
115  }
116  
117  APIRecord::~APIRecord() {}
118  TagRecord::~TagRecord() {}
119  RecordRecord::~RecordRecord() {}
120  RecordFieldRecord::~RecordFieldRecord() {}
121  ObjCContainerRecord::~ObjCContainerRecord() {}
122  ObjCMethodRecord::~ObjCMethodRecord() {}
123  ObjCPropertyRecord::~ObjCPropertyRecord() {}
124  CXXMethodRecord::~CXXMethodRecord() {}
125  
126  void GlobalFunctionRecord::anchor() {}
127  void GlobalVariableRecord::anchor() {}
128  void EnumConstantRecord::anchor() {}
129  void EnumRecord::anchor() {}
130  void StructFieldRecord::anchor() {}
131  void StructRecord::anchor() {}
132  void UnionFieldRecord::anchor() {}
133  void UnionRecord::anchor() {}
134  void CXXFieldRecord::anchor() {}
135  void CXXClassRecord::anchor() {}
136  void CXXConstructorRecord::anchor() {}
137  void CXXDestructorRecord::anchor() {}
138  void CXXInstanceMethodRecord::anchor() {}
139  void CXXStaticMethodRecord::anchor() {}
140  void ObjCInstancePropertyRecord::anchor() {}
141  void ObjCClassPropertyRecord::anchor() {}
142  void ObjCInstanceVariableRecord::anchor() {}
143  void ObjCInstanceMethodRecord::anchor() {}
144  void ObjCClassMethodRecord::anchor() {}
145  void ObjCCategoryRecord::anchor() {}
146  void ObjCInterfaceRecord::anchor() {}
147  void ObjCProtocolRecord::anchor() {}
148  void MacroDefinitionRecord::anchor() {}
149  void TypedefRecord::anchor() {}
150