blob: 70676f0e1410948def27fbed68f113a5fa649a1d [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 Gregora88084b2010-02-18 18:08:43 +000018#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000019#include "llvm/Support/MemoryBuffer.h"
20
Douglas Gregor5352ac02010-01-28 00:27:43 +000021using namespace clang;
22using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000023using namespace clang::cxstring;
Douglas Gregora88084b2010-02-18 18:08:43 +000024using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000025
26//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000027// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000028//-----------------------------------------------------------------------------
29extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000030
Douglas Gregora88084b2010-02-18 18:08:43 +000031unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
32 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
33 return CXXUnit? CXXUnit->diag_size() : 0;
34}
35
36CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
37 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
38 if (!CXXUnit || Index >= CXXUnit->diag_size())
39 return 0;
40
41 return new CXStoredDiagnostic(CXXUnit->diag_begin()[Index],
42 CXXUnit->getASTContext().getLangOptions());
43}
44
45void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
46 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
47 delete Stored;
48}
49
Douglas Gregor5352ac02010-01-28 00:27:43 +000050enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
51 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
52 if (!StoredDiag)
53 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000054
Douglas Gregora88084b2010-02-18 18:08:43 +000055 switch (StoredDiag->Diag.getLevel()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +000056 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
57 case Diagnostic::Note: return CXDiagnostic_Note;
58 case Diagnostic::Warning: return CXDiagnostic_Warning;
59 case Diagnostic::Error: return CXDiagnostic_Error;
60 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
61 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +000062
Douglas Gregor5352ac02010-01-28 00:27:43 +000063 llvm_unreachable("Invalid diagnostic level");
64 return CXDiagnostic_Ignored;
65}
Ted Kremenekee4db4f2010-02-17 00:41:08 +000066
Douglas Gregor5352ac02010-01-28 00:27:43 +000067CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
68 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +000069 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +000070 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +000071
Douglas Gregora88084b2010-02-18 18:08:43 +000072 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
73 StoredDiag->LangOpts,
74 StoredDiag->Diag.getLocation());
Douglas Gregor5352ac02010-01-28 00:27:43 +000075}
76
77CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
78 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
79 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +000080 return createCXString("");
81
Douglas Gregora88084b2010-02-18 18:08:43 +000082 return createCXString(StoredDiag->Diag.getMessage(), false);
Douglas Gregor5352ac02010-01-28 00:27:43 +000083}
84
Douglas Gregora3890ba2010-02-08 23:11:56 +000085unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +000086 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +000087 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +000088 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000089
Douglas Gregora88084b2010-02-18 18:08:43 +000090 return StoredDiag->Diag.range_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +000091}
Ted Kremenekee4db4f2010-02-17 00:41:08 +000092
Douglas Gregora3890ba2010-02-08 23:11:56 +000093CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
94 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +000095 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
96 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +000097 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +000098
Douglas Gregora88084b2010-02-18 18:08:43 +000099 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
100 StoredDiag->LangOpts,
101 StoredDiag->Diag.range_begin()[Range]);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000102}
103
104unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
105 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
106 if (!StoredDiag)
107 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000108
Douglas Gregora88084b2010-02-18 18:08:43 +0000109 return StoredDiag->Diag.fixit_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000110}
111
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000112enum CXFixItKind clang_getDiagnosticFixItKind(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000113 unsigned FixIt) {
114 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000115 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000116 return CXFixIt_Insertion;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000117
Douglas Gregora88084b2010-02-18 18:08:43 +0000118 const CodeModificationHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor5352ac02010-01-28 00:27:43 +0000119 if (Hint.RemoveRange.isInvalid())
120 return CXFixIt_Insertion;
121 if (Hint.InsertionLoc.isInvalid())
122 return CXFixIt_Removal;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000123
124 return CXFixIt_Replacement;
Douglas Gregor5352ac02010-01-28 00:27:43 +0000125}
126
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000127CXString clang_getDiagnosticFixItInsertion(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000128 unsigned FixIt,
129 CXSourceLocation *Location) {
Douglas Gregor51c6d382010-01-29 00:41:11 +0000130 if (Location)
131 *Location = clang_getNullLocation();
132
Douglas Gregor5352ac02010-01-28 00:27:43 +0000133 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000134 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size())
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000135 return createCXString("");
136
Douglas Gregora88084b2010-02-18 18:08:43 +0000137 const CodeModificationHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor51c6d382010-01-29 00:41:11 +0000138
Douglas Gregora88084b2010-02-18 18:08:43 +0000139 if (Location && StoredDiag->Diag.getLocation().isValid())
Douglas Gregor51c6d382010-01-29 00:41:11 +0000140 *Location = translateSourceLocation(
Douglas Gregora88084b2010-02-18 18:08:43 +0000141 StoredDiag->Diag.getLocation().getManager(),
142 StoredDiag->LangOpts,
Douglas Gregor51c6d382010-01-29 00:41:11 +0000143 Hint.InsertionLoc);
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000144 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000145}
146
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000147CXSourceRange clang_getDiagnosticFixItRemoval(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000148 unsigned FixIt) {
149 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000150 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
151 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000152 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000153
Douglas Gregora88084b2010-02-18 18:08:43 +0000154 const CodeModificationHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
155 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
156 StoredDiag->LangOpts,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000157 Hint.RemoveRange);
158}
159
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000160CXString clang_getDiagnosticFixItReplacement(CXDiagnostic Diag,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000161 unsigned FixIt,
162 CXSourceRange *Range) {
Douglas Gregor51c6d382010-01-29 00:41:11 +0000163 if (Range)
164 *Range = clang_getNullRange();
165
Douglas Gregor5352ac02010-01-28 00:27:43 +0000166 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000167 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
168 StoredDiag->Diag.getLocation().isInvalid()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000169 if (Range)
170 *Range = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000171
172 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000173 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000174
Douglas Gregora88084b2010-02-18 18:08:43 +0000175 const CodeModificationHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor5352ac02010-01-28 00:27:43 +0000176 if (Range)
Douglas Gregora88084b2010-02-18 18:08:43 +0000177 *Range = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
178 StoredDiag->LangOpts,
Douglas Gregor5352ac02010-01-28 00:27:43 +0000179 Hint.RemoveRange);
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000180 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000181}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000182
Douglas Gregor5352ac02010-01-28 00:27:43 +0000183} // end extern "C"
Douglas Gregord93256e2010-01-28 06:00:51 +0000184
Douglas Gregora88084b2010-02-18 18:08:43 +0000185void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
186 unsigned num_unsaved_files,
187 struct CXUnsavedFile *unsaved_files,
188 FileManager &FileMgr,
189 SourceManager &SourceMgr,
190 SmallVectorImpl<StoredDiagnostic> &Diags) {
Douglas Gregord93256e2010-01-28 06:00:51 +0000191 using llvm::MemoryBuffer;
192 using llvm::StringRef;
193 MemoryBuffer *F = MemoryBuffer::getFile(DiagnosticsPath.c_str());
194 if (!F)
195 return;
196
197 // Enter the unsaved files into the file manager.
Douglas Gregord93256e2010-01-28 06:00:51 +0000198 for (unsigned I = 0; I != num_unsaved_files; ++I) {
199 const FileEntry *File = FileMgr.getVirtualFile(unsaved_files[I].Filename,
200 unsaved_files[I].Length,
201 0);
202 if (!File) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000203 // FIXME: Hard to localize when we have no diagnostics engine!
204 Diags.push_back(StoredDiagnostic(Diagnostic::Fatal,
205 (Twine("could not remap from missing file ") +
206 unsaved_files[I].Filename).str()));
Douglas Gregord93256e2010-01-28 06:00:51 +0000207 return;
208 }
209
210 MemoryBuffer *Buffer
211 = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
212 unsaved_files[I].Contents + unsaved_files[I].Length);
213 if (!Buffer)
214 return;
215
216 SourceMgr.overrideFileContents(File, Buffer);
217 }
218
219 // Parse the diagnostics, emitting them one by one until we've
220 // exhausted the data.
221 StringRef Buffer = F->getBuffer();
222 const char *Memory = Buffer.data(), *MemoryEnd = Memory + Buffer.size();
223 while (Memory != MemoryEnd) {
Douglas Gregora88084b2010-02-18 18:08:43 +0000224 StoredDiagnostic Stored = StoredDiagnostic::Deserialize(FileMgr, SourceMgr,
225 Memory, MemoryEnd);
226 if (!Stored)
Douglas Gregord93256e2010-01-28 06:00:51 +0000227 return;
Daniel Dunbar35b84402010-01-30 23:31:40 +0000228
Douglas Gregora88084b2010-02-18 18:08:43 +0000229 Diags.push_back(Stored);
230 }
Douglas Gregord93256e2010-01-28 06:00:51 +0000231}