|
37 | 37 | #include "clang/AST/Mangle.h" |
38 | 38 | #include "clang/AST/MangleNumberingContext.h" |
39 | 39 | #include "clang/AST/NestedNameSpecifier.h" |
| 40 | +#include "clang/AST/ObjCMethodReferenceInfo.h" |
40 | 41 | #include "clang/AST/ParentMapContext.h" |
41 | 42 | #include "clang/AST/RawCommentList.h" |
42 | 43 | #include "clang/AST/RecordLayout.h" |
|
85 | 86 | #include "llvm/Support/Casting.h" |
86 | 87 | #include "llvm/Support/Compiler.h" |
87 | 88 | #include "llvm/Support/ErrorHandling.h" |
| 89 | +#include "llvm/Support/JSON.h" |
88 | 90 | #include "llvm/Support/MD5.h" |
89 | 91 | #include "llvm/Support/MathExtras.h" |
90 | 92 | #include "llvm/Support/SipHash.h" |
@@ -9241,6 +9243,133 @@ static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { |
9241 | 9243 | return Context->buildImplicitTypedef(T, "__builtin_va_list"); |
9242 | 9244 | } |
9243 | 9245 |
|
| 9246 | +bool ASTContext::isObjCMsgSendUsageFileSpecified() const { |
| 9247 | + if (!ObjCMsgSendUsageFile) { |
| 9248 | + if (const char *Filename = |
| 9249 | + std::getenv("CLANG_COMPILER_OBJC_MESSAGE_TRACE_PATH")) |
| 9250 | + ObjCMsgSendUsageFile = Filename; |
| 9251 | + else |
| 9252 | + return false; |
| 9253 | + } |
| 9254 | + |
| 9255 | + return true; |
| 9256 | +} |
| 9257 | + |
| 9258 | +std::string ASTContext::getObjCMsgSendUsageFilename() const { |
| 9259 | + if (isObjCMsgSendUsageFileSpecified()) |
| 9260 | + return *ObjCMsgSendUsageFile; |
| 9261 | + return ""; |
| 9262 | +} |
| 9263 | + |
| 9264 | +void ASTContext::recordObjCMsgSendUsage(const ObjCMethodDecl *Method) { |
| 9265 | + ObjCMsgSendUsage.push_back(Method); |
| 9266 | +} |
| 9267 | + |
| 9268 | +static StringRef selectMethodKey(const clang::ObjCMethodDecl *clangD) { |
| 9269 | + assert(clangD); |
| 9270 | + if (clangD->isInstanceMethod()) |
| 9271 | + return "instance_method"; |
| 9272 | + assert(clangD->isClassMethod() && "must be a class method"); |
| 9273 | + return "class_method"; |
| 9274 | +} |
| 9275 | + |
| 9276 | +static std::array<std::pair<StringRef, StringRef>, 2> |
| 9277 | +selectMethodOwnerKey(const clang::NamedDecl *clangD) { |
| 9278 | + assert(clangD); |
| 9279 | + if (isa<clang::ObjCInterfaceDecl>(clangD)) |
| 9280 | + return {{{"interface_type", clangD->getName()}, {}}}; |
| 9281 | + if (isa<clang::ObjCImplementationDecl>(clangD)) |
| 9282 | + return {{{"implementation_type", clangD->getName()}, {}}}; |
| 9283 | + if (auto *Cat = dyn_cast<clang::ObjCCategoryDecl>(clangD)) |
| 9284 | + return {{{"interface_type", Cat->getClassInterface()->getName()}, |
| 9285 | + {"category_type", Cat->getName()}}}; |
| 9286 | + if (auto *Cat = dyn_cast<clang::ObjCCategoryImplDecl>(clangD)) |
| 9287 | + return {{{"interface_type", |
| 9288 | + Cat->getCategoryDecl()->getClassInterface()->getName()}, |
| 9289 | + {"category_implementation_type", Cat->getName()}}}; |
| 9290 | + if (isa<clang::ObjCProtocolDecl>(clangD)) |
| 9291 | + return {{{"protocol_type", clangD->getName()}, {}}}; |
| 9292 | + llvm_unreachable("unknown method owner"); |
| 9293 | +} |
| 9294 | + |
| 9295 | +void clang::serializeObjCMethodReferencesAsJson( |
| 9296 | + const clang::ObjCMethodReferenceInfo &Info, llvm::raw_ostream &OS) { |
| 9297 | + llvm::json::OStream Out(OS, /*IndentSize=*/4); |
| 9298 | + Out.object([&] { |
| 9299 | + Out.attribute("format-version", Info.FormatVersion); |
| 9300 | + Out.attribute("target", Info.Target); |
| 9301 | + if (!Info.TargetVariant.empty()) |
| 9302 | + Out.attribute("target-variant", Info.TargetVariant); |
| 9303 | + Out.attributeArray("references", [&] { |
| 9304 | + for (auto &Ref : Info.References) { |
| 9305 | + unsigned FileID = Ref.first; |
| 9306 | + for (const clang::ObjCMethodDecl *clangD : Ref.second) { |
| 9307 | + auto &SM = clangD->getASTContext().getSourceManager(); |
| 9308 | + clang::SourceLocation Loc = clangD->getLocation(); |
| 9309 | + if (!Loc.isValid()) |
| 9310 | + continue; |
| 9311 | + Out.object([&] { |
| 9312 | + if (auto *parent = |
| 9313 | + dyn_cast_or_null<clang::NamedDecl>(clangD->getParent())) { |
| 9314 | + std::array<std::pair<StringRef, StringRef>, 2> OwnerInfo = |
| 9315 | + selectMethodOwnerKey(parent); |
| 9316 | + for (auto I : OwnerInfo) |
| 9317 | + if (I.first.data()) |
| 9318 | + Out.attribute(I.first, I.second); |
| 9319 | + } |
| 9320 | + |
| 9321 | + std::string MangledMethodName; |
| 9322 | + llvm::raw_string_ostream Out2(MangledMethodName); |
| 9323 | + std::unique_ptr<MangleContext> Mangler( |
| 9324 | + clangD->getASTContext().createMangleContext()); |
| 9325 | + Mangler->mangleObjCMethodName(clangD, Out2, |
| 9326 | + /*includePrefixByte=*/false, true); |
| 9327 | + Out.attribute(selectMethodKey(clangD), MangledMethodName); |
| 9328 | + Out.attribute("declared_at", Loc.printToString(SM)); |
| 9329 | + Out.attribute("referenced_at_file_id", FileID); |
| 9330 | + }); |
| 9331 | + } |
| 9332 | + } |
| 9333 | + }); |
| 9334 | + |
| 9335 | + Out.attributeArray("fileMap", [&] { |
| 9336 | + for (unsigned I = 0, N = Info.FilePaths.size(); I != N; I++) { |
| 9337 | + Out.object([&] { |
| 9338 | + Out.attribute("file_id", I + 1); |
| 9339 | + Out.attribute("file_path", Info.FilePaths[I]); |
| 9340 | + }); |
| 9341 | + } |
| 9342 | + }); |
| 9343 | + }); |
| 9344 | +} |
| 9345 | + |
| 9346 | +void ASTContext::writeObjCMsgSendUsages(const std::string &Filename) { |
| 9347 | + std::error_code EC; |
| 9348 | + auto FDS = std::make_unique<llvm::raw_fd_ostream>( |
| 9349 | + Filename, EC, llvm::sys::fs::OF_Text | llvm::sys::fs::OF_Append); |
| 9350 | + if (EC) { |
| 9351 | + unsigned ID = getDiagnostics().getCustomDiagID( |
| 9352 | + DiagnosticsEngine::Error, |
| 9353 | + "couldn't open objc message send tracing file %0"); |
| 9354 | + getDiagnostics().Report(ID) << Filename; |
| 9355 | + return; |
| 9356 | + } |
| 9357 | + |
| 9358 | + if (auto L = FDS->lock()) { |
| 9359 | + clang::ObjCMethodReferenceInfo Info; |
| 9360 | + OptionalFileEntryRef FE = |
| 9361 | + SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID()); |
| 9362 | + SmallString<256> MainFile(FE->getName()); |
| 9363 | + SourceMgr.getFileManager().makeAbsolutePath(MainFile); |
| 9364 | + Info.Target = getTargetInfo().getTriple().str(); |
| 9365 | + if (auto *VariantTriple = getTargetInfo().getDarwinTargetVariantTriple()) |
| 9366 | + Info.TargetVariant = VariantTriple->str(); |
| 9367 | + Info.FilePaths.push_back(MainFile.c_str()); |
| 9368 | + Info.References[1] = ObjCMsgSendUsage; |
| 9369 | + serializeObjCMethodReferencesAsJson(Info, *FDS); |
| 9370 | + } |
| 9371 | +} |
| 9372 | + |
9244 | 9373 | static TypedefDecl * |
9245 | 9374 | CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { |
9246 | 9375 | // struct __va_list |
|
0 commit comments