blob: 5c18c9534fee244096473ad2887f81ac972f7dcf [file] [log] [blame]
Douglas Gregor5352ac02010-01-28 00:27:43 +00001/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface -----------*- C -*-===*\
2|* *|
3|* The LLVM Compiler Infrastructure *|
4|* *|
5|* This file is distributed under the University of Illinois Open Source *|
6|* License. See LICENSE.TXT for details. *|
7|* *|
8|*===----------------------------------------------------------------------===*|
9|* *|
10|* Implements the diagnostic functions of the Clang C interface. *|
11|* *|
12\*===----------------------------------------------------------------------===*/
13#include "CIndexDiagnostic.h"
14#include "CIndexer.h"
15#include "CXSourceLocation.h"
16
Douglas Gregord93256e2010-01-28 06:00:51 +000017#include "clang/Frontend/FrontendDiagnostic.h"
18#include "llvm/Support/MemoryBuffer.h"
19
Douglas Gregor5352ac02010-01-28 00:27:43 +000020using namespace clang;
21using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000022using namespace clang::cxstring;
Douglas Gregor5352ac02010-01-28 00:27:43 +000023
24//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000025// Opaque data structures
Douglas Gregor5352ac02010-01-28 00:27:43 +000026//-----------------------------------------------------------------------------
27namespace {
28 /// \brief The storage behind a CXDiagnostic
29 struct CXStoredDiagnostic {
30 /// \brief The translation unit this diagnostic came from.
Daniel Dunbar49146122010-01-30 23:31:49 +000031 const LangOptions *LangOptsPtr;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000032
Douglas Gregor5352ac02010-01-28 00:27:43 +000033 /// \brief The severity level of this diagnostic.
34 Diagnostic::Level Level;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000035
Douglas Gregor5352ac02010-01-28 00:27:43 +000036 /// \brief A reference to the diagnostic information.
37 const DiagnosticInfo &Info;
38 };
39}
40
41//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000042// CIndex Diagnostic Client
Douglas Gregor5352ac02010-01-28 00:27:43 +000043//-----------------------------------------------------------------------------
44CIndexDiagnosticClient::~CIndexDiagnosticClient() { }
45
46void CIndexDiagnosticClient::BeginSourceFile(const LangOptions &LangOpts,
47 const Preprocessor *PP) {
Daniel Dunbar49146122010-01-30 23:31:49 +000048 assert(!LangOptsPtr && "Invalid state!");
49 LangOptsPtr = &LangOpts;
50}
51
52void CIndexDiagnosticClient::EndSourceFile() {
53 assert(LangOptsPtr && "Invalid state!");
54 LangOptsPtr = 0;
Douglas Gregor5352ac02010-01-28 00:27:43 +000055}
56
57void CIndexDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
58 const DiagnosticInfo &Info) {
59 if (!Callback)
60 return;
Daniel Dunbar49146122010-01-30 23:31:49 +000061
62 assert((LangOptsPtr || Info.getLocation().isInvalid()) &&
63 "Missing language options with located diagnostic!");
64 CXStoredDiagnostic Stored = { this->LangOptsPtr, DiagLevel, Info };
Douglas Gregor5352ac02010-01-28 00:27:43 +000065 Callback(&Stored, ClientData);
66}
67
68//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000069// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000070//-----------------------------------------------------------------------------
71extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000072
Douglas Gregor5352ac02010-01-28 00:27:43 +000073enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
74 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
75 if (!StoredDiag)
76 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000077
Douglas Gregor5352ac02010-01-28 00:27:43 +000078 switch (StoredDiag->Level) {
79 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
80 case Diagnostic::Note: return CXDiagnostic_Note;
81 case Diagnostic::Warning: return CXDiagnostic_Warning;
82 case Diagnostic::Error: return CXDiagnostic_Error;
83 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
84 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +000085
Douglas Gregor5352ac02010-01-28 00:27:43 +000086 llvm_unreachable("Invalid diagnostic level");
87 return CXDiagnostic_Ignored;
88}
Ted Kremenekee4db4f2010-02-17 00:41:08 +000089
Douglas Gregor5352ac02010-01-28 00:27:43 +000090CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
91 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
92 if (!StoredDiag || StoredDiag->Info.getLocation().isInvalid())
93 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +000094
Douglas Gregor5352ac02010-01-28 00:27:43 +000095 return translateSourceLocation(StoredDiag->Info.getLocation().getManager(),
Daniel Dunbar49146122010-01-30 23:31:49 +000096 *StoredDiag->LangOptsPtr,
Douglas Gregor5352ac02010-01-28 00:27:43 +000097 StoredDiag->Info.getLocation());
98}
99
100CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
101 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
102 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000103 return createCXString("");
104
Douglas Gregor5352ac02010-01-28 00:27:43 +0000105 llvm::SmallString<64> Spelling;
106 StoredDiag->Info.FormatDiagnostic(Spelling);
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000107 return createCXString(Spelling.str(), true);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000108}
109
Douglas Gregora3890ba2010-02-08 23:11:56 +0000110unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000111 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora3890ba2010-02-08 23:11:56 +0000112 if (!StoredDiag || StoredDiag->Info.getLocation().isInvalid())
113 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000114
Douglas Gregora3890ba2010-02-08 23:11:56 +0000115 return StoredDiag->Info.getNumRanges();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000116}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000117
Douglas Gregora3890ba2010-02-08 23:11:56 +0000118CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
119 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000120 if (!StoredDiag || Range >= StoredDiag->Info.getNumRanges() ||
Douglas Gregora3890ba2010-02-08 23:11:56 +0000121 StoredDiag->Info.getLocation().isInvalid())
122 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000123
Douglas Gregora3890ba2010-02-08 23:11:56 +0000124 return translateSourceRange(StoredDiag->Info.getLocation().getManager(),
125 *StoredDiag->LangOptsPtr,
126 StoredDiag->Info.getRange(Range));
Douglas Gregor5352ac02010-01-28 00:27:43 +0000127}
128
129unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
130 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
131 if (!StoredDiag)
132 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000133
Douglas Gregor5352ac02010-01-28 00:27:43 +0000134 return StoredDiag->Info.getNumCodeModificationHints();
135}
136
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000137enum CXFixItKind clang_getDiagnosticFixItKind(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000138 unsigned FixIt) {
139 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
140 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
141 return CXFixIt_Insertion;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000142
Douglas Gregor5352ac02010-01-28 00:27:43 +0000143 const CodeModificationHint &Hint
144 = StoredDiag->Info.getCodeModificationHint(FixIt);
145 if (Hint.RemoveRange.isInvalid())
146 return CXFixIt_Insertion;
147 if (Hint.InsertionLoc.isInvalid())
148 return CXFixIt_Removal;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000149
150 return CXFixIt_Replacement;
Douglas Gregor5352ac02010-01-28 00:27:43 +0000151}
152
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000153CXString clang_getDiagnosticFixItInsertion(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000154 unsigned FixIt,
155 CXSourceLocation *Location) {
Douglas Gregor51c6d382010-01-29 00:41:11 +0000156 if (Location)
157 *Location = clang_getNullLocation();
158
Douglas Gregor5352ac02010-01-28 00:27:43 +0000159 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
160 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints())
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000161 return createCXString("");
162
Douglas Gregor5352ac02010-01-28 00:27:43 +0000163 const CodeModificationHint &Hint
164 = StoredDiag->Info.getCodeModificationHint(FixIt);
Douglas Gregor51c6d382010-01-29 00:41:11 +0000165
166 if (Location && StoredDiag->Info.getLocation().isValid())
167 *Location = translateSourceLocation(
168 StoredDiag->Info.getLocation().getManager(),
Daniel Dunbar49146122010-01-30 23:31:49 +0000169 *StoredDiag->LangOptsPtr,
Douglas Gregor51c6d382010-01-29 00:41:11 +0000170 Hint.InsertionLoc);
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000171 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000172}
173
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000174CXSourceRange clang_getDiagnosticFixItRemoval(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000175 unsigned FixIt) {
176 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
177 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
178 StoredDiag->Info.getLocation().isInvalid())
179 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000180
Douglas Gregor5352ac02010-01-28 00:27:43 +0000181 const CodeModificationHint &Hint
182 = StoredDiag->Info.getCodeModificationHint(FixIt);
183 return translateSourceRange(StoredDiag->Info.getLocation().getManager(),
Daniel Dunbar49146122010-01-30 23:31:49 +0000184 *StoredDiag->LangOptsPtr,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000185 Hint.RemoveRange);
186}
187
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000188CXString clang_getDiagnosticFixItReplacement(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000189 unsigned FixIt,
190 CXSourceRange *Range) {
Douglas Gregor51c6d382010-01-29 00:41:11 +0000191 if (Range)
192 *Range = clang_getNullRange();
193
Douglas Gregor5352ac02010-01-28 00:27:43 +0000194 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
195 if (!StoredDiag || FixIt >= StoredDiag->Info.getNumCodeModificationHints() ||
196 StoredDiag->Info.getLocation().isInvalid()) {
197 if (Range)
198 *Range = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000199
200 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000201 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000202
Douglas Gregor5352ac02010-01-28 00:27:43 +0000203 const CodeModificationHint &Hint
204 = StoredDiag->Info.getCodeModificationHint(FixIt);
205 if (Range)
206 *Range = translateSourceRange(StoredDiag->Info.getLocation().getManager(),
Daniel Dunbar49146122010-01-30 23:31:49 +0000207 *StoredDiag->LangOptsPtr,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000208 Hint.RemoveRange);
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000209 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000210}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000211
Douglas Gregor5352ac02010-01-28 00:27:43 +0000212} // end extern "C"
Douglas Gregord93256e2010-01-28 06:00:51 +0000213
214void clang::ReportSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
215 Diagnostic &Diags,
216 unsigned num_unsaved_files,
Daniel Dunbar35b84402010-01-30 23:31:40 +0000217 struct CXUnsavedFile *unsaved_files,
218 const LangOptions &LangOpts) {
Douglas Gregord93256e2010-01-28 06:00:51 +0000219 using llvm::MemoryBuffer;
220 using llvm::StringRef;
221 MemoryBuffer *F = MemoryBuffer::getFile(DiagnosticsPath.c_str());
222 if (!F)
223 return;
224
225 // Enter the unsaved files into the file manager.
226 SourceManager SourceMgr;
227 FileManager FileMgr;
228 for (unsigned I = 0; I != num_unsaved_files; ++I) {
229 const FileEntry *File = FileMgr.getVirtualFile(unsaved_files[I].Filename,
230 unsaved_files[I].Length,
231 0);
232 if (!File) {
233 Diags.Report(diag::err_fe_remap_missing_from_file)
234 << unsaved_files[I].Filename;
235 return;
236 }
237
238 MemoryBuffer *Buffer
239 = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
240 unsaved_files[I].Contents + unsaved_files[I].Length);
241 if (!Buffer)
242 return;
243
244 SourceMgr.overrideFileContents(File, Buffer);
245 }
246
Daniel Dunbar35b84402010-01-30 23:31:40 +0000247 Diags.getClient()->BeginSourceFile(LangOpts, 0);
248
Douglas Gregord93256e2010-01-28 06:00:51 +0000249 // Parse the diagnostics, emitting them one by one until we've
250 // exhausted the data.
251 StringRef Buffer = F->getBuffer();
252 const char *Memory = Buffer.data(), *MemoryEnd = Memory + Buffer.size();
253 while (Memory != MemoryEnd) {
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000254 DiagnosticBuilder DB = Diags.Deserialize(FileMgr, SourceMgr,
Douglas Gregord93256e2010-01-28 06:00:51 +0000255 Memory, MemoryEnd);
256 if (!DB.isActive())
257 return;
258 }
Daniel Dunbar35b84402010-01-30 23:31:40 +0000259
260 Diags.getClient()->EndSourceFile();
Douglas Gregord93256e2010-01-28 06:00:51 +0000261}