//===--- StandaloneDiagnostic.h - Serializable Diagnostic ------------- ---===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Frontend/StandaloneDiagnostic.h" #include "clang/Lex/Lexer.h" namespace clang { StandaloneDiagnostic::SourceOffsetRange::SourceOffsetRange( CharSourceRange Range, const SourceManager &SrcMgr, const LangOptions &LangOpts) { const auto FileRange = Lexer::makeFileCharRange(Range, SrcMgr, LangOpts); Begin = SrcMgr.getFileOffset(FileRange.getBegin()); End = SrcMgr.getFileOffset(FileRange.getEnd()); } StandaloneDiagnostic::StandaloneFixIt::StandaloneFixIt( const SourceManager &SrcMgr, const LangOptions &LangOpts, const FixItHint &FixIt) : RemoveRange(FixIt.RemoveRange, SrcMgr, LangOpts), InsertFromRange(FixIt.InsertFromRange, SrcMgr, LangOpts), CodeToInsert(FixIt.CodeToInsert), BeforePreviousInsertions(FixIt.BeforePreviousInsertions) {} StandaloneDiagnostic::StandaloneDiagnostic(const LangOptions &LangOpts, const StoredDiagnostic &InDiag) : Level(InDiag.getLevel()), ID(InDiag.getID()), Message(InDiag.getMessage()) { const FullSourceLoc &FullLoc = InDiag.getLocation(); // This is not an invalid diagnostic; invalid SourceLocations are used to // represent diagnostics without a specific SourceLocation. if (FullLoc.isInvalid()) return; const auto &SrcMgr = FullLoc.getManager(); FileKind = SrcMgr.getFileCharacteristic(static_cast(FullLoc)); const auto FileLoc = SrcMgr.getFileLoc(static_cast(FullLoc)); FileOffset = SrcMgr.getFileOffset(FileLoc); Filename = SrcMgr.getFilename(FileLoc); assert(!Filename.empty() && "diagnostic with location has no source file?"); Ranges.reserve(InDiag.getRanges().size()); for (const auto &Range : InDiag.getRanges()) Ranges.emplace_back(Range, SrcMgr, LangOpts); FixIts.reserve(InDiag.getFixIts().size()); for (const auto &FixIt : InDiag.getFixIts()) FixIts.emplace_back(SrcMgr, LangOpts, FixIt); } StoredDiagnostic translateStandaloneDiag(FileManager &FileMgr, SourceManager &SrcMgr, const StandaloneDiagnostic &StandaloneDiag, llvm::StringMap &SrcLocCache) { const auto FileRef = FileMgr.getOptionalFileRef(StandaloneDiag.Filename); if (!FileRef) return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID, StandaloneDiag.Message); // Try to get FileLoc from cache first SourceLocation FileLoc; auto It = SrcLocCache.find(StandaloneDiag.Filename); if (It != SrcLocCache.end()) { FileLoc = It->getValue(); } // Cache miss - compute and cache the location if (FileLoc.isInvalid()) { const auto FileID = SrcMgr.getOrCreateFileID(*FileRef, StandaloneDiag.FileKind); FileLoc = SrcMgr.getLocForStartOfFile(FileID); if (FileLoc.isInvalid()) return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID, StandaloneDiag.Message); SrcLocCache[StandaloneDiag.Filename] = FileLoc; } const auto DiagLoc = FileLoc.getLocWithOffset(StandaloneDiag.FileOffset); const FullSourceLoc Loc(DiagLoc, SrcMgr); auto ConvertOffsetRange = [&](const StandaloneDiagnostic::SourceOffsetRange &Range) { return CharSourceRange( SourceRange(FileLoc.getLocWithOffset(Range.Begin), FileLoc.getLocWithOffset(Range.End)), /*IsTokenRange*/ false); }; SmallVector TranslatedRanges; TranslatedRanges.reserve(StandaloneDiag.Ranges.size()); transform(StandaloneDiag.Ranges, std::back_inserter(TranslatedRanges), ConvertOffsetRange); SmallVector TranslatedFixIts; TranslatedFixIts.reserve(StandaloneDiag.FixIts.size()); for (const auto &FixIt : StandaloneDiag.FixIts) { FixItHint TranslatedFixIt; TranslatedFixIt.CodeToInsert = FixIt.CodeToInsert; TranslatedFixIt.RemoveRange = ConvertOffsetRange(FixIt.RemoveRange); TranslatedFixIt.InsertFromRange = ConvertOffsetRange(FixIt.InsertFromRange); TranslatedFixIt.BeforePreviousInsertions = FixIt.BeforePreviousInsertions; TranslatedFixIts.push_back(std::move(TranslatedFixIt)); } return StoredDiagnostic(StandaloneDiag.Level, StandaloneDiag.ID, StandaloneDiag.Message, Loc, TranslatedRanges, TranslatedFixIts); } } // namespace clang