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/CommentCommandTraits.h" 17 #include "clang/AST/CommentLexer.h" 18 #include "clang/AST/RawCommentList.h" 19 #include "clang/Index/USRGeneration.h" 20 #include <memory> 21 22 using namespace clang::extractapi; 23 using namespace llvm; 24 25 GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR, 26 PresumedLoc Loc, 27 const AvailabilityInfo &Availability, 28 LinkageInfo Linkage, const DocComment &Comment, 29 DeclarationFragments Fragments, 30 DeclarationFragments SubHeading, 31 FunctionSignature Signature) { 32 auto Result = Globals.insert({Name, nullptr}); 33 if (Result.second) { 34 // Create the record if it does not already exist. 35 auto Record = std::make_unique<GlobalRecord>( 36 Kind, Name, USR, Loc, Availability, Linkage, Comment, Fragments, 37 SubHeading, Signature); 38 Result.first->second = std::move(Record); 39 } 40 return Result.first->second.get(); 41 } 42 43 GlobalRecord * 44 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, 45 const AvailabilityInfo &Availability, LinkageInfo Linkage, 46 const DocComment &Comment, DeclarationFragments Fragments, 47 DeclarationFragments SubHeading) { 48 return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage, 49 Comment, Fragments, SubHeading, {}); 50 } 51 52 GlobalRecord * 53 APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc, 54 const AvailabilityInfo &Availability, LinkageInfo Linkage, 55 const DocComment &Comment, DeclarationFragments Fragments, 56 DeclarationFragments SubHeading, 57 FunctionSignature Signature) { 58 return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage, 59 Comment, Fragments, SubHeading, Signature); 60 } 61 62 EnumConstantRecord *APISet::addEnumConstant( 63 EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc, 64 const AvailabilityInfo &Availability, const DocComment &Comment, 65 DeclarationFragments Declaration, DeclarationFragments SubHeading) { 66 auto Record = std::make_unique<EnumConstantRecord>( 67 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 68 return Enum->Constants.emplace_back(std::move(Record)).get(); 69 } 70 71 EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, 72 const AvailabilityInfo &Availability, 73 const DocComment &Comment, 74 DeclarationFragments Declaration, 75 DeclarationFragments SubHeading) { 76 auto Result = Enums.insert({Name, nullptr}); 77 if (Result.second) { 78 // Create the record if it does not already exist. 79 auto Record = std::make_unique<EnumRecord>( 80 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 81 Result.first->second = std::move(Record); 82 } 83 return Result.first->second.get(); 84 } 85 86 StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name, 87 StringRef USR, PresumedLoc Loc, 88 const AvailabilityInfo &Availability, 89 const DocComment &Comment, 90 DeclarationFragments Declaration, 91 DeclarationFragments SubHeading) { 92 auto Record = std::make_unique<StructFieldRecord>( 93 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 94 return Struct->Fields.emplace_back(std::move(Record)).get(); 95 } 96 97 StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc, 98 const AvailabilityInfo &Availability, 99 const DocComment &Comment, 100 DeclarationFragments Declaration, 101 DeclarationFragments SubHeading) { 102 auto Result = Structs.insert({Name, nullptr}); 103 if (Result.second) { 104 // Create the record if it does not already exist. 105 auto Record = std::make_unique<StructRecord>( 106 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 107 Result.first->second = std::move(Record); 108 } 109 return Result.first->second.get(); 110 } 111 112 StringRef APISet::recordUSR(const Decl *D) { 113 SmallString<128> USR; 114 index::generateUSRForDecl(D, USR); 115 return copyString(USR); 116 } 117 118 StringRef APISet::copyString(StringRef String) { 119 if (String.empty()) 120 return {}; 121 122 // No need to allocate memory and copy if the string has already been stored. 123 if (StringAllocator.identifyObject(String.data())) 124 return String; 125 126 void *Ptr = StringAllocator.Allocate(String.size(), 1); 127 memcpy(Ptr, String.data(), String.size()); 128 return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 129 } 130 131 APIRecord::~APIRecord() {} 132 133 void GlobalRecord::anchor() {} 134 void EnumConstantRecord::anchor() {} 135 void EnumRecord::anchor() {} 136 void StructFieldRecord::anchor() {} 137 void StructRecord::anchor() {} 138