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(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(String.data())) 106 return String; 107 108 void *Ptr = Allocator.Allocate(String.size(), 1); 109 memcpy(Ptr, String.data(), 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(Name), copyString(USR), copyString(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