blob: 0314a67d07d1294ff0fbdcf91b832c028ccbce2c [file] [log] [blame]
Douglas Gregora88084b2010-02-18 18:08:43 +00001/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
Douglas Gregor5352ac02010-01-28 00:27:43 +00002|* *|
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"
Douglas Gregor274f1902010-02-22 23:17:23 +000018#include "llvm/ADT/SmallString.h"
Douglas Gregora88084b2010-02-18 18:08:43 +000019#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000020#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000021#include "llvm/Support/raw_ostream.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000022
Douglas Gregor5352ac02010-01-28 00:27:43 +000023using namespace clang;
24using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000025using namespace clang::cxstring;
Douglas Gregora88084b2010-02-18 18:08:43 +000026using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000027
28//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000029// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000030//-----------------------------------------------------------------------------
31extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000032
Douglas Gregora88084b2010-02-18 18:08:43 +000033unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
34 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
35 return CXXUnit? CXXUnit->diag_size() : 0;
36}
37
38CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
39 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
40 if (!CXXUnit || Index >= CXXUnit->diag_size())
41 return 0;
42
43 return new CXStoredDiagnostic(CXXUnit->diag_begin()[Index],
44 CXXUnit->getASTContext().getLangOptions());
45}
46
47void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
48 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
49 delete Stored;
50}
51
Douglas Gregor274f1902010-02-22 23:17:23 +000052CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
53 if (!Diagnostic)
54 return createCXString("");
Douglas Gregor0a812cf2010-02-18 23:07:20 +000055
56 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
57
58 // Ignore diagnostics that should be ignored.
59 if (Severity == CXDiagnostic_Ignored)
Douglas Gregor274f1902010-02-22 23:17:23 +000060 return createCXString("");
Douglas Gregor0a812cf2010-02-18 23:07:20 +000061
Douglas Gregor274f1902010-02-22 23:17:23 +000062 llvm::SmallString<256> Str;
63 llvm::raw_svector_ostream Out(Str);
64
Douglas Gregor0a812cf2010-02-18 23:07:20 +000065 if (Options & CXDiagnostic_DisplaySourceLocation) {
66 // Print source location (file:line), along with optional column
67 // and source ranges.
68 CXFile File;
69 unsigned Line, Column;
70 clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
71 &File, &Line, &Column, 0);
72 if (File) {
73 CXString FName = clang_getFileName(File);
Douglas Gregor274f1902010-02-22 23:17:23 +000074 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000075 clang_disposeString(FName);
76 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregor274f1902010-02-22 23:17:23 +000077 Out << Column << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000078
79 if (Options & CXDiagnostic_DisplaySourceRanges) {
80 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
81 bool PrintedRange = false;
82 for (unsigned I = 0; I != N; ++I) {
83 CXFile StartFile, EndFile;
84 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
85
86 unsigned StartLine, StartColumn, EndLine, EndColumn;
87 clang_getInstantiationLocation(clang_getRangeStart(Range),
88 &StartFile, &StartLine, &StartColumn,
89 0);
90 clang_getInstantiationLocation(clang_getRangeEnd(Range),
91 &EndFile, &EndLine, &EndColumn, 0);
92
93 if (StartFile != EndFile || StartFile != File)
94 continue;
95
Douglas Gregor274f1902010-02-22 23:17:23 +000096 Out << "{" << StartLine << ":" << StartColumn << "-"
97 << EndLine << ":" << EndColumn << "}";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000098 PrintedRange = true;
99 }
100 if (PrintedRange)
Douglas Gregor274f1902010-02-22 23:17:23 +0000101 Out << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000102 }
103 }
104
Douglas Gregor274f1902010-02-22 23:17:23 +0000105 Out << " ";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000106 }
107
108 /* Print warning/error/etc. */
109 switch (Severity) {
110 case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
Douglas Gregor274f1902010-02-22 23:17:23 +0000111 case CXDiagnostic_Note: Out << "note: "; break;
112 case CXDiagnostic_Warning: Out << "warning: "; break;
113 case CXDiagnostic_Error: Out << "error: "; break;
114 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000115 }
116
117 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
118 if (clang_getCString(Text))
Douglas Gregor274f1902010-02-22 23:17:23 +0000119 Out << clang_getCString(Text);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000120 else
Douglas Gregor274f1902010-02-22 23:17:23 +0000121 Out << "<no diagnostic text>";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000122 clang_disposeString(Text);
Douglas Gregor274f1902010-02-22 23:17:23 +0000123 return createCXString(Out.str(), true);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000124}
125
126unsigned clang_defaultDiagnosticDisplayOptions() {
127 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn;
128}
129
Douglas Gregor5352ac02010-01-28 00:27:43 +0000130enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
131 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
132 if (!StoredDiag)
133 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000134
Douglas Gregora88084b2010-02-18 18:08:43 +0000135 switch (StoredDiag->Diag.getLevel()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000136 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
137 case Diagnostic::Note: return CXDiagnostic_Note;
138 case Diagnostic::Warning: return CXDiagnostic_Warning;
139 case Diagnostic::Error: return CXDiagnostic_Error;
140 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
141 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000142
Douglas Gregor5352ac02010-01-28 00:27:43 +0000143 llvm_unreachable("Invalid diagnostic level");
144 return CXDiagnostic_Ignored;
145}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000146
Douglas Gregor5352ac02010-01-28 00:27:43 +0000147CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
148 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000149 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000150 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000151
Douglas Gregora88084b2010-02-18 18:08:43 +0000152 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
153 StoredDiag->LangOpts,
154 StoredDiag->Diag.getLocation());
Douglas Gregor5352ac02010-01-28 00:27:43 +0000155}
156
157CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
158 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
159 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000160 return createCXString("");
161
Douglas Gregora88084b2010-02-18 18:08:43 +0000162 return createCXString(StoredDiag->Diag.getMessage(), false);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000163}
164
Douglas Gregora3890ba2010-02-08 23:11:56 +0000165unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000166 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000167 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000168 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000169
Douglas Gregora88084b2010-02-18 18:08:43 +0000170 return StoredDiag->Diag.range_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000171}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000172
Douglas Gregora3890ba2010-02-08 23:11:56 +0000173CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
174 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000175 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
176 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000177 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000178
Douglas Gregora88084b2010-02-18 18:08:43 +0000179 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
180 StoredDiag->LangOpts,
181 StoredDiag->Diag.range_begin()[Range]);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000182}
183
184unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
185 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
186 if (!StoredDiag)
187 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000188
Douglas Gregora88084b2010-02-18 18:08:43 +0000189 return StoredDiag->Diag.fixit_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000190}
191
Douglas Gregor473d7012010-02-19 18:16:06 +0000192CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
193 CXSourceRange *ReplacementRange) {
194 CXStoredDiagnostic *StoredDiag
195 = static_cast<CXStoredDiagnostic *>(Diagnostic);
Douglas Gregora88084b2010-02-18 18:08:43 +0000196 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
197 StoredDiag->Diag.getLocation().isInvalid()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000198 if (ReplacementRange)
199 *ReplacementRange = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000200
201 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000202 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000203
Douglas Gregord0ebe082010-03-31 15:31:50 +0000204 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor473d7012010-02-19 18:16:06 +0000205 if (ReplacementRange) {
206 if (Hint.RemoveRange.isInvalid()) {
207 // Create an empty range that refers to a single source
208 // location (which is the insertion point).
209 CXSourceRange Range = {
210 { (void *)&StoredDiag->Diag.getLocation().getManager(),
211 (void *)&StoredDiag->LangOpts },
212 Hint.InsertionLoc.getRawEncoding(),
213 Hint.InsertionLoc.getRawEncoding()
214 };
215
216 *ReplacementRange = Range;
217 } else {
218 // Create a range that covers the entire replacement (or
219 // removal) range, adjusting the end of the range to point to
220 // the end of the token.
221 *ReplacementRange
222 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
223 StoredDiag->LangOpts,
224 Hint.RemoveRange);
225 }
226 }
227
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000228 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000229}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000230
Douglas Gregor5352ac02010-01-28 00:27:43 +0000231} // end extern "C"
Douglas Gregord93256e2010-01-28 06:00:51 +0000232
Douglas Gregora88084b2010-02-18 18:08:43 +0000233void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
234 unsigned num_unsaved_files,
235 struct CXUnsavedFile *unsaved_files,
236 FileManager &FileMgr,
237 SourceManager &SourceMgr,
238 SmallVectorImpl<StoredDiagnostic> &Diags) {
Douglas Gregord93256e2010-01-28 06:00:51 +0000239 using llvm::MemoryBuffer;
240 using llvm::StringRef;
241 MemoryBuffer *F = MemoryBuffer::getFile(DiagnosticsPath.c_str());
242 if (!F)
243 return;
244
245 // Enter the unsaved files into the file manager.
Douglas Gregord93256e2010-01-28 06:00:51 +0000246 for (unsigned I = 0; I != num_unsaved_files; ++I) {
247 const FileEntry *File = FileMgr.getVirtualFile(unsaved_files[I].Filename,
248 unsaved_files[I].Length,
249 0);
250 if (!File) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000251 // FIXME: Hard to localize when we have no diagnostics engine!
252 Diags.push_back(StoredDiagnostic(Diagnostic::Fatal,
253 (Twine("could not remap from missing file ") +
254 unsaved_files[I].Filename).str()));
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000255 delete F;
Douglas Gregord93256e2010-01-28 06:00:51 +0000256 return;
257 }
258
259 MemoryBuffer *Buffer
260 = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
261 unsaved_files[I].Contents + unsaved_files[I].Length);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000262 if (!Buffer) {
263 delete F;
Douglas Gregord93256e2010-01-28 06:00:51 +0000264 return;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000265 }
266
Douglas Gregord93256e2010-01-28 06:00:51 +0000267 SourceMgr.overrideFileContents(File, Buffer);
Douglas Gregorf7353c02010-03-24 21:04:06 +0000268 SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
Douglas Gregord93256e2010-01-28 06:00:51 +0000269 }
270
271 // Parse the diagnostics, emitting them one by one until we've
272 // exhausted the data.
273 StringRef Buffer = F->getBuffer();
274 const char *Memory = Buffer.data(), *MemoryEnd = Memory + Buffer.size();
275 while (Memory != MemoryEnd) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000276 StoredDiagnostic Stored = StoredDiagnostic::Deserialize(FileMgr, SourceMgr,
277 Memory, MemoryEnd);
278 if (!Stored)
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000279 break;
Daniel Dunbar35b84402010-01-30 23:31:40 +0000280
Douglas Gregora88084b2010-02-18 18:08:43 +0000281 Diags.push_back(Stored);
282 }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000283 delete F;
Douglas Gregord93256e2010-01-28 06:00:51 +0000284}