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 "llvm/ADT/STLFunctionalExtras.h" 21 #include "llvm/ADT/StringRef.h" 22 #include <memory> 23 24 using namespace clang::extractapi; 25 using namespace llvm; 26 27 namespace { 28 29 template <typename RecordTy, typename... CtorArgsTy> 30 RecordTy *addTopLevelRecord(APISet::RecordMap<RecordTy> &RecordMap, 31 StringRef Name, CtorArgsTy &&...CtorArgs) { 32 auto Result = RecordMap.insert({Name, nullptr}); 33 34 // Create the record if it does not already exist 35 if (Result.second) 36 Result.first->second = 37 std::make_unique<RecordTy>(Name, std::forward<CtorArgsTy>(CtorArgs)...); 38 39 return Result.first->second.get(); 40 } 41 42 } // namespace 43 44 GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR, 45 PresumedLoc Loc, 46 const AvailabilityInfo &Availability, 47 LinkageInfo Linkage, const DocComment &Comment, 48 DeclarationFragments Fragments, 49 DeclarationFragments SubHeading, 50 FunctionSignature Signature) { 51 return addTopLevelRecord(Globals, Name, USR, Loc, Availability, Linkage, 52 Comment, Fragments, SubHeading, Kind, Signature); 53 } 54 55 GlobalRecord * 56 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, 57 const AvailabilityInfo &Availability, LinkageInfo Linkage, 58 const DocComment &Comment, DeclarationFragments Fragments, 59 DeclarationFragments SubHeading) { 60 return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage, 61 Comment, Fragments, SubHeading, {}); 62 } 63 64 GlobalRecord * 65 APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc, 66 const AvailabilityInfo &Availability, LinkageInfo Linkage, 67 const DocComment &Comment, DeclarationFragments Fragments, 68 DeclarationFragments SubHeading, 69 FunctionSignature Signature) { 70 return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage, 71 Comment, Fragments, SubHeading, Signature); 72 } 73 74 EnumConstantRecord *APISet::addEnumConstant( 75 EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc, 76 const AvailabilityInfo &Availability, const DocComment &Comment, 77 DeclarationFragments Declaration, DeclarationFragments SubHeading) { 78 auto Record = std::make_unique<EnumConstantRecord>( 79 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 80 return Enum->Constants.emplace_back(std::move(Record)).get(); 81 } 82 83 EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, 84 const AvailabilityInfo &Availability, 85 const DocComment &Comment, 86 DeclarationFragments Declaration, 87 DeclarationFragments SubHeading) { 88 return addTopLevelRecord(Enums, Name, USR, Loc, Availability, Comment, 89 Declaration, SubHeading); 90 } 91 92 StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name, 93 StringRef USR, PresumedLoc Loc, 94 const AvailabilityInfo &Availability, 95 const DocComment &Comment, 96 DeclarationFragments Declaration, 97 DeclarationFragments SubHeading) { 98 auto Record = std::make_unique<StructFieldRecord>( 99 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 100 return Struct->Fields.emplace_back(std::move(Record)).get(); 101 } 102 103 StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc, 104 const AvailabilityInfo &Availability, 105 const DocComment &Comment, 106 DeclarationFragments Declaration, 107 DeclarationFragments SubHeading) { 108 return addTopLevelRecord(Structs, Name, USR, Loc, Availability, Comment, 109 Declaration, SubHeading); 110 } 111 112 ObjCInterfaceRecord *APISet::addObjCInterface( 113 StringRef Name, StringRef USR, PresumedLoc Loc, 114 const AvailabilityInfo &Availability, LinkageInfo Linkage, 115 const DocComment &Comment, DeclarationFragments Declaration, 116 DeclarationFragments SubHeading, SymbolReference SuperClass) { 117 return addTopLevelRecord(ObjCInterfaces, Name, USR, Loc, Availability, 118 Linkage, Comment, Declaration, SubHeading, 119 SuperClass); 120 } 121 122 ObjCMethodRecord *APISet::addObjCMethod( 123 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 124 PresumedLoc Loc, const AvailabilityInfo &Availability, 125 const DocComment &Comment, DeclarationFragments Declaration, 126 DeclarationFragments SubHeading, FunctionSignature Signature, 127 bool IsInstanceMethod) { 128 auto Record = std::make_unique<ObjCMethodRecord>( 129 Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature, 130 IsInstanceMethod); 131 return Container->Methods.emplace_back(std::move(Record)).get(); 132 } 133 134 ObjCPropertyRecord *APISet::addObjCProperty( 135 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 136 PresumedLoc Loc, const AvailabilityInfo &Availability, 137 const DocComment &Comment, DeclarationFragments Declaration, 138 DeclarationFragments SubHeading, 139 ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName, 140 StringRef SetterName, bool IsOptional) { 141 auto Record = std::make_unique<ObjCPropertyRecord>( 142 Name, USR, Loc, Availability, Comment, Declaration, SubHeading, 143 Attributes, GetterName, SetterName, IsOptional); 144 return Container->Properties.emplace_back(std::move(Record)).get(); 145 } 146 147 ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable( 148 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 149 PresumedLoc Loc, const AvailabilityInfo &Availability, 150 const DocComment &Comment, DeclarationFragments Declaration, 151 DeclarationFragments SubHeading, 152 ObjCInstanceVariableRecord::AccessControl Access) { 153 auto Record = std::make_unique<ObjCInstanceVariableRecord>( 154 Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access); 155 return Container->Ivars.emplace_back(std::move(Record)).get(); 156 } 157 158 ObjCProtocolRecord *APISet::addObjCProtocol( 159 StringRef Name, StringRef USR, PresumedLoc Loc, 160 const AvailabilityInfo &Availability, const DocComment &Comment, 161 DeclarationFragments Declaration, DeclarationFragments SubHeading) { 162 return addTopLevelRecord(ObjCProtocols, Name, USR, Loc, Availability, Comment, 163 Declaration, SubHeading); 164 } 165 166 MacroDefinitionRecord * 167 APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc, 168 DeclarationFragments Declaration, 169 DeclarationFragments SubHeading) { 170 return addTopLevelRecord(Macros, Name, USR, Loc, Declaration, SubHeading); 171 } 172 173 StringRef APISet::recordUSR(const Decl *D) { 174 SmallString<128> USR; 175 index::generateUSRForDecl(D, USR); 176 return copyString(USR); 177 } 178 179 StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL, 180 const SourceManager &SM) { 181 SmallString<128> USR; 182 index::generateUSRForMacro(Name, SL, SM, USR); 183 return copyString(USR); 184 } 185 186 StringRef APISet::copyString(StringRef String) { 187 if (String.empty()) 188 return {}; 189 190 // No need to allocate memory and copy if the string has already been stored. 191 if (StringAllocator.identifyObject(String.data())) 192 return String; 193 194 void *Ptr = StringAllocator.Allocate(String.size(), 1); 195 memcpy(Ptr, String.data(), String.size()); 196 return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 197 } 198 199 APIRecord::~APIRecord() {} 200 201 ObjCContainerRecord::~ObjCContainerRecord() {} 202 203 void GlobalRecord::anchor() {} 204 void EnumConstantRecord::anchor() {} 205 void EnumRecord::anchor() {} 206 void StructFieldRecord::anchor() {} 207 void StructRecord::anchor() {} 208 void ObjCPropertyRecord::anchor() {} 209 void ObjCInstanceVariableRecord::anchor() {} 210 void ObjCMethodRecord::anchor() {} 211 void ObjCInterfaceRecord::anchor() {} 212 void ObjCProtocolRecord::anchor() {} 213 void MacroDefinitionRecord::anchor() {} 214