xref: /freebsd-src/contrib/llvm-project/clang/lib/ExtractAPI/API.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===- ExtractAPI/API.cpp ---------------------------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric ///
981ad6265SDimitry Andric /// \file
1081ad6265SDimitry Andric /// This file implements the APIRecord and derived record structs,
1181ad6265SDimitry Andric /// and the APISet class.
1281ad6265SDimitry Andric ///
1381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1481ad6265SDimitry Andric 
1581ad6265SDimitry Andric #include "clang/ExtractAPI/API.h"
1681ad6265SDimitry Andric #include "clang/AST/RawCommentList.h"
1781ad6265SDimitry Andric #include "clang/Index/USRGeneration.h"
1881ad6265SDimitry Andric #include "llvm/ADT/StringRef.h"
19*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
2081ad6265SDimitry Andric #include <memory>
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric using namespace clang::extractapi;
2381ad6265SDimitry Andric using namespace llvm;
2481ad6265SDimitry Andric 
25*0fca6ea1SDimitry Andric SymbolReference::SymbolReference(const APIRecord *R)
26*0fca6ea1SDimitry Andric     : Name(R->Name), USR(R->USR), Record(R) {}
2781ad6265SDimitry Andric 
28*0fca6ea1SDimitry Andric APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) {
29*0fca6ea1SDimitry Andric   switch (Ctx->getKind()) {
30*0fca6ea1SDimitry Andric #define RECORD_CONTEXT(CLASS, KIND)                                            \
31*0fca6ea1SDimitry Andric   case KIND:                                                                   \
32*0fca6ea1SDimitry Andric     return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
33*0fca6ea1SDimitry Andric #include "clang/ExtractAPI/APIRecords.inc"
34*0fca6ea1SDimitry Andric   default:
35*0fca6ea1SDimitry Andric     return nullptr;
36*0fca6ea1SDimitry Andric     // llvm_unreachable("RecordContext derived class isn't propertly
37*0fca6ea1SDimitry Andric     // implemented");
38*0fca6ea1SDimitry Andric   }
3981ad6265SDimitry Andric }
4081ad6265SDimitry Andric 
41*0fca6ea1SDimitry Andric RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
42*0fca6ea1SDimitry Andric   if (!Record)
43*0fca6ea1SDimitry Andric     return nullptr;
44*0fca6ea1SDimitry Andric   switch (Record->getKind()) {
45*0fca6ea1SDimitry Andric #define RECORD_CONTEXT(CLASS, KIND)                                            \
46*0fca6ea1SDimitry Andric   case KIND:                                                                   \
47*0fca6ea1SDimitry Andric     return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
48*0fca6ea1SDimitry Andric #include "clang/ExtractAPI/APIRecords.inc"
49*0fca6ea1SDimitry Andric   default:
50*0fca6ea1SDimitry Andric     return nullptr;
51*0fca6ea1SDimitry Andric     // llvm_unreachable("RecordContext derived class isn't propertly
52*0fca6ea1SDimitry Andric     // implemented");
53*0fca6ea1SDimitry Andric   }
545f757f3fSDimitry Andric }
555f757f3fSDimitry Andric 
56*0fca6ea1SDimitry Andric bool RecordContext::IsWellFormed() const {
57*0fca6ea1SDimitry Andric   // Check that First and Last are both null or both non-null.
58*0fca6ea1SDimitry Andric   return (First == nullptr) == (Last == nullptr);
5981ad6265SDimitry Andric }
6081ad6265SDimitry Andric 
61*0fca6ea1SDimitry Andric void RecordContext::stealRecordChain(RecordContext &Other) {
62*0fca6ea1SDimitry Andric   assert(IsWellFormed());
63*0fca6ea1SDimitry Andric   // If we don't have an empty chain append Other's chain into ours.
64*0fca6ea1SDimitry Andric   if (First)
65*0fca6ea1SDimitry Andric     Last->NextInContext = Other.First;
66bdd1243dSDimitry Andric   else
67*0fca6ea1SDimitry Andric     First = Other.First;
68bdd1243dSDimitry Andric 
69*0fca6ea1SDimitry Andric   Last = Other.Last;
70*0fca6ea1SDimitry Andric 
71*0fca6ea1SDimitry Andric   // Delete Other's chain to ensure we don't accidentally traverse it.
72*0fca6ea1SDimitry Andric   Other.First = nullptr;
73*0fca6ea1SDimitry Andric   Other.Last = nullptr;
7481ad6265SDimitry Andric }
7581ad6265SDimitry Andric 
76*0fca6ea1SDimitry Andric void RecordContext::addToRecordChain(APIRecord *Record) const {
77*0fca6ea1SDimitry Andric   assert(IsWellFormed());
78*0fca6ea1SDimitry Andric   if (!First) {
79*0fca6ea1SDimitry Andric     First = Record;
80*0fca6ea1SDimitry Andric     Last = Record;
81*0fca6ea1SDimitry Andric     return;
8281ad6265SDimitry Andric   }
8381ad6265SDimitry Andric 
84*0fca6ea1SDimitry Andric   Last->NextInContext = Record;
85*0fca6ea1SDimitry Andric   Last = Record;
86bdd1243dSDimitry Andric }
87bdd1243dSDimitry Andric 
88bdd1243dSDimitry Andric APIRecord *APISet::findRecordForUSR(StringRef USR) const {
89bdd1243dSDimitry Andric   if (USR.empty())
90bdd1243dSDimitry Andric     return nullptr;
91bdd1243dSDimitry Andric 
92*0fca6ea1SDimitry Andric   auto FindIt = USRBasedLookupTable.find(USR);
93*0fca6ea1SDimitry Andric   if (FindIt != USRBasedLookupTable.end())
94*0fca6ea1SDimitry Andric     return FindIt->getSecond().get();
9581ad6265SDimitry Andric 
96*0fca6ea1SDimitry Andric   return nullptr;
9781ad6265SDimitry Andric }
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric StringRef APISet::copyString(StringRef String) {
10081ad6265SDimitry Andric   if (String.empty())
10181ad6265SDimitry Andric     return {};
10281ad6265SDimitry Andric 
10381ad6265SDimitry Andric   // No need to allocate memory and copy if the string has already been stored.
104*0fca6ea1SDimitry Andric   if (Allocator.identifyObject(String.data()))
10581ad6265SDimitry Andric     return String;
10681ad6265SDimitry Andric 
107*0fca6ea1SDimitry Andric   void *Ptr = Allocator.Allocate(String.size(), 1);
10881ad6265SDimitry Andric   memcpy(Ptr, String.data(), String.size());
10981ad6265SDimitry Andric   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
11081ad6265SDimitry Andric }
11181ad6265SDimitry Andric 
112*0fca6ea1SDimitry Andric SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
113*0fca6ea1SDimitry Andric                                               StringRef Source) {
114*0fca6ea1SDimitry Andric   return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
115*0fca6ea1SDimitry Andric }
116*0fca6ea1SDimitry Andric 
11781ad6265SDimitry Andric APIRecord::~APIRecord() {}
118*0fca6ea1SDimitry Andric TagRecord::~TagRecord() {}
119*0fca6ea1SDimitry Andric RecordRecord::~RecordRecord() {}
120*0fca6ea1SDimitry Andric RecordFieldRecord::~RecordFieldRecord() {}
12181ad6265SDimitry Andric ObjCContainerRecord::~ObjCContainerRecord() {}
122bdd1243dSDimitry Andric ObjCMethodRecord::~ObjCMethodRecord() {}
123bdd1243dSDimitry Andric ObjCPropertyRecord::~ObjCPropertyRecord() {}
1245f757f3fSDimitry Andric CXXMethodRecord::~CXXMethodRecord() {}
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric void GlobalFunctionRecord::anchor() {}
12781ad6265SDimitry Andric void GlobalVariableRecord::anchor() {}
12881ad6265SDimitry Andric void EnumConstantRecord::anchor() {}
12981ad6265SDimitry Andric void EnumRecord::anchor() {}
130*0fca6ea1SDimitry Andric void StructFieldRecord::anchor() {}
131*0fca6ea1SDimitry Andric void StructRecord::anchor() {}
132*0fca6ea1SDimitry Andric void UnionFieldRecord::anchor() {}
133*0fca6ea1SDimitry Andric void UnionRecord::anchor() {}
1345f757f3fSDimitry Andric void CXXFieldRecord::anchor() {}
1355f757f3fSDimitry Andric void CXXClassRecord::anchor() {}
1365f757f3fSDimitry Andric void CXXConstructorRecord::anchor() {}
1375f757f3fSDimitry Andric void CXXDestructorRecord::anchor() {}
1385f757f3fSDimitry Andric void CXXInstanceMethodRecord::anchor() {}
1395f757f3fSDimitry Andric void CXXStaticMethodRecord::anchor() {}
140bdd1243dSDimitry Andric void ObjCInstancePropertyRecord::anchor() {}
141bdd1243dSDimitry Andric void ObjCClassPropertyRecord::anchor() {}
14281ad6265SDimitry Andric void ObjCInstanceVariableRecord::anchor() {}
143bdd1243dSDimitry Andric void ObjCInstanceMethodRecord::anchor() {}
144bdd1243dSDimitry Andric void ObjCClassMethodRecord::anchor() {}
14581ad6265SDimitry Andric void ObjCCategoryRecord::anchor() {}
14681ad6265SDimitry Andric void ObjCInterfaceRecord::anchor() {}
14781ad6265SDimitry Andric void ObjCProtocolRecord::anchor() {}
14881ad6265SDimitry Andric void MacroDefinitionRecord::anchor() {}
14981ad6265SDimitry Andric void TypedefRecord::anchor() {}
150