1 /*===-- CIndexDiagnostics.cpp - Diagnostics C Interface -----------*- C -*-===*\
3 |* The LLVM Compiler Infrastructure *|
5 |* This file is distributed under the University of Illinois Open Source *|
6 |* License. See LICENSE.TXT for details. *|
8 |*===----------------------------------------------------------------------===*|
10 |* Implements the diagnostic functions of the Clang C interface. *|
12 \*===----------------------------------------------------------------------===*/
13 #include "CIndexDiagnostic.h"
15 #include "CXSourceLocation.h"
17 #include "clang/Frontend/FrontendDiagnostic.h"
18 #include "llvm/Support/MemoryBuffer.h"
20 using namespace clang;
21 using namespace clang::cxloc;
23 //-----------------------------------------------------------------------------
24 // Opaque data structures
25 //-----------------------------------------------------------------------------
27 /// \brief The storage behind a CXDiagnostic
28 struct CXStoredDiagnostic {
29 /// \brief The translation unit this diagnostic came from.
30 const LangOptions *LangOptsPtr;
32 /// \brief The severity level of this diagnostic.
33 Diagnostic::Level Level;
35 /// \brief A reference to the diagnostic information.
36 const DiagnosticInfo &Info;
40 //-----------------------------------------------------------------------------
41 // CIndex Diagnostic Client
42 //-----------------------------------------------------------------------------
43 CIndexDiagnosticClient::~CIndexDiagnosticClient() { }
45 void CIndexDiagnosticClient::BeginSourceFile(const LangOptions &LangOpts,
46 const Preprocessor *PP) {
47 assert(!LangOptsPtr && "Invalid state!");
48 LangOptsPtr = &LangOpts;
51 void CIndexDiagnosticClient::EndSourceFile() {
52 assert(LangOptsPtr && "Invalid state!");
56 void CIndexDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
57 const DiagnosticInfo &Info) {
61 assert((LangOptsPtr || Info.getLocation().isInvalid()) &&
62 "Missing language options with located diagnostic!");
63 CXStoredDiagnostic Stored = { this->LangOptsPtr, DiagLevel, Info };
64 Callback(&Stored, ClientData);
67 //-----------------------------------------------------------------------------
68 // C Interface Routines
69 //-----------------------------------------------------------------------------
72 enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
73 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
75 return CXDiagnostic_Ignored;
77 switch (StoredDiag->Level) {
78 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
79 case Diagnostic::Note: return CXDiagnostic_Note;
80 case Diagnostic::Warning: return CXDiagnostic_Warning;
81 case Diagnostic::Error: return CXDiagnostic_Error;
82 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
85 llvm_unreachable("Invalid diagnostic level");
86 return CXDiagnostic_Ignored;
89 CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
90 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
91 if (!StoredDiag || StoredDiag->Info.getLocation().isInvalid())
92 return clang_getNullLocation();
94 return translateSourceLocation(StoredDiag->Info.getLocation().getManager(),
95 *StoredDiag->LangOptsPtr,
96 StoredDiag->Info.getLocation());
99 CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
100 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
102 return CIndexer::createCXString("");
104 llvm::SmallString<64> Spelling;
105 StoredDiag->Info.FormatDiagnostic(Spelling);
106 return CIndexer::createCXString(Spelling.str(), true);
109 unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
110 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
111 if (!StoredDiag || StoredDiag->Info.getLocation().isInvalid())
114 return StoredDiag->Info.getNumRanges();
117 CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
118 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
119 if (!StoredDiag || Range >= StoredDiag->Info.getNumRanges() ||
120 StoredDiag->Info.getLocation().isInvalid())
121 return clang_getNullRange();
123 return translateSourceRange(StoredDiag->Info.getLocation().getManager(),
124 *StoredDiag->LangOptsPtr,
125 StoredDiag->Info.getRange(Range));
128 unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
129 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
133 return StoredDiag->Info.getNumCodeModificationHints();
136 enum CXFixItKind clang_getDiagnosticFixItKind(CXDiagnostic Diag,
138 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
139 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
140 return CXFixIt_Insertion;
142 const CodeModificationHint &Hint
143 = StoredDiag->Info.getCodeModificationHint(FixIt);
144 if (Hint.RemoveRange.isInvalid())
145 return CXFixIt_Insertion;
146 if (Hint.InsertionLoc.isInvalid())
147 return CXFixIt_Removal;
149 return CXFixIt_Replacement;
152 CXString clang_getDiagnosticFixItInsertion(CXDiagnostic Diag,
154 CXSourceLocation *Location) {
156 *Location = clang_getNullLocation();
158 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
159 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
160 return CIndexer::createCXString("");
162 const CodeModificationHint &Hint
163 = StoredDiag->Info.getCodeModificationHint(FixIt);
165 if (Location && StoredDiag->Info.getLocation().isValid())
166 *Location = translateSourceLocation(
167 StoredDiag->Info.getLocation().getManager(),
168 *StoredDiag->LangOptsPtr,
170 return CIndexer::createCXString(Hint.CodeToInsert);
173 CXSourceRange clang_getDiagnosticFixItRemoval(CXDiagnostic Diag,
175 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
176 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
177 StoredDiag->Info.getLocation().isInvalid())
178 return clang_getNullRange();
180 const CodeModificationHint &Hint
181 = StoredDiag->Info.getCodeModificationHint(FixIt);
182 return translateSourceRange(StoredDiag->Info.getLocation().getManager(),
183 *StoredDiag->LangOptsPtr,
187 CXString clang_getDiagnosticFixItReplacement(CXDiagnostic Diag,
189 CXSourceRange *Range) {
191 *Range = clang_getNullRange();
193 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
194 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
195 StoredDiag->Info.getLocation().isInvalid()) {
197 *Range = clang_getNullRange();
199 return CIndexer::createCXString("");
202 const CodeModificationHint &Hint
203 = StoredDiag->Info.getCodeModificationHint(FixIt);
205 *Range = translateSourceRange(StoredDiag->Info.getLocation().getManager(),
206 *StoredDiag->LangOptsPtr,
208 return CIndexer::createCXString(Hint.CodeToInsert);
213 void clang::ReportSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
215 unsigned num_unsaved_files,
216 struct CXUnsavedFile *unsaved_files,
217 const LangOptions &LangOpts) {
218 using llvm::MemoryBuffer;
219 using llvm::StringRef;
220 MemoryBuffer *F = MemoryBuffer::getFile(DiagnosticsPath.c_str());
224 // Enter the unsaved files into the file manager.
225 SourceManager SourceMgr;
227 for (unsigned I = 0; I != num_unsaved_files; ++I) {
228 const FileEntry *File = FileMgr.getVirtualFile(unsaved_files[I].Filename,
229 unsaved_files[I].Length,
232 Diags.Report(diag::err_fe_remap_missing_from_file)
233 << unsaved_files[I].Filename;
238 = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
239 unsaved_files[I].Contents + unsaved_files[I].Length);
243 SourceMgr.overrideFileContents(File, Buffer);
246 Diags.getClient()->BeginSourceFile(LangOpts, 0);
248 // Parse the diagnostics, emitting them one by one until we've
249 // exhausted the data.
250 StringRef Buffer = F->getBuffer();
251 const char *Memory = Buffer.data(), *MemoryEnd = Memory + Buffer.size();
252 while (Memory != MemoryEnd) {
253 DiagnosticBuilder DB = Diags.Deserialize(FileMgr, SourceMgr,
259 Diags.getClient()->EndSourceFile();