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