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 "CXTranslationUnit.h"
16 #include "CXSourceLocation.h"
19 #include "clang/Frontend/ASTUnit.h"
20 #include "clang/Frontend/FrontendDiagnostic.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/raw_ostream.h"
26 using namespace clang
;
27 using namespace clang::cxloc
;
28 using namespace clang::cxstring
;
31 //-----------------------------------------------------------------------------
32 // C Interface Routines
33 //-----------------------------------------------------------------------------
36 unsigned clang_getNumDiagnostics(CXTranslationUnit Unit
) {
37 ASTUnit
*CXXUnit
= static_cast<ASTUnit
*>(Unit
->TUData
);
38 return CXXUnit
? CXXUnit
->stored_diag_size() : 0;
41 CXDiagnostic
clang_getDiagnostic(CXTranslationUnit Unit
, unsigned Index
) {
42 ASTUnit
*CXXUnit
= static_cast<ASTUnit
*>(Unit
->TUData
);
43 if (!CXXUnit
|| Index
>= CXXUnit
->stored_diag_size())
46 return new CXStoredDiagnostic(CXXUnit
->stored_diag_begin()[Index
],
47 CXXUnit
->getASTContext().getLangOptions());
50 void clang_disposeDiagnostic(CXDiagnostic Diagnostic
) {
51 CXStoredDiagnostic
*Stored
= static_cast<CXStoredDiagnostic
*>(Diagnostic
);
55 CXString
clang_formatDiagnostic(CXDiagnostic Diagnostic
, unsigned Options
) {
57 return createCXString("");
59 CXDiagnosticSeverity Severity
= clang_getDiagnosticSeverity(Diagnostic
);
61 llvm::SmallString
<256> Str
;
62 llvm::raw_svector_ostream
Out(Str
);
64 if (Options
& CXDiagnostic_DisplaySourceLocation
) {
65 // Print source location (file:line), along with optional column
68 unsigned Line
, Column
;
69 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic
),
70 &File
, &Line
, &Column
, 0);
72 CXString FName
= clang_getFileName(File
);
73 Out
<< clang_getCString(FName
) << ":" << Line
<< ":";
74 clang_disposeString(FName
);
75 if (Options
& CXDiagnostic_DisplayColumn
)
78 if (Options
& CXDiagnostic_DisplaySourceRanges
) {
79 unsigned N
= clang_getDiagnosticNumRanges(Diagnostic
);
80 bool PrintedRange
= false;
81 for (unsigned I
= 0; I
!= N
; ++I
) {
82 CXFile StartFile
, EndFile
;
83 CXSourceRange Range
= clang_getDiagnosticRange(Diagnostic
, I
);
85 unsigned StartLine
, StartColumn
, EndLine
, EndColumn
;
86 clang_getSpellingLocation(clang_getRangeStart(Range
),
87 &StartFile
, &StartLine
, &StartColumn
,
89 clang_getSpellingLocation(clang_getRangeEnd(Range
),
90 &EndFile
, &EndLine
, &EndColumn
, 0);
92 if (StartFile
!= EndFile
|| StartFile
!= File
)
95 Out
<< "{" << StartLine
<< ":" << StartColumn
<< "-"
96 << EndLine
<< ":" << EndColumn
<< "}";
107 /* Print warning/error/etc. */
109 case CXDiagnostic_Ignored
: assert(0 && "impossible"); break;
110 case CXDiagnostic_Note
: Out
<< "note: "; break;
111 case CXDiagnostic_Warning
: Out
<< "warning: "; break;
112 case CXDiagnostic_Error
: Out
<< "error: "; break;
113 case CXDiagnostic_Fatal
: Out
<< "fatal error: "; break;
116 CXString Text
= clang_getDiagnosticSpelling(Diagnostic
);
117 if (clang_getCString(Text
))
118 Out
<< clang_getCString(Text
);
120 Out
<< "<no diagnostic text>";
121 clang_disposeString(Text
);
123 if (Options
& (CXDiagnostic_DisplayOption
| CXDiagnostic_DisplayCategoryId
|
124 CXDiagnostic_DisplayCategoryName
)) {
125 bool NeedBracket
= true;
126 bool NeedComma
= false;
128 if (Options
& CXDiagnostic_DisplayOption
) {
129 CXString OptionName
= clang_getDiagnosticOption(Diagnostic
, 0);
130 if (const char *OptionText
= clang_getCString(OptionName
)) {
132 Out
<< " [" << OptionText
;
137 clang_disposeString(OptionName
);
140 if (Options
& (CXDiagnostic_DisplayCategoryId
|
141 CXDiagnostic_DisplayCategoryName
)) {
142 if (unsigned CategoryID
= clang_getDiagnosticCategory(Diagnostic
)) {
143 if (Options
& CXDiagnostic_DisplayCategoryId
) {
153 if (Options
& CXDiagnostic_DisplayCategoryName
) {
154 CXString CategoryName
= clang_getDiagnosticCategoryName(CategoryID
);
159 Out
<< clang_getCString(CategoryName
);
162 clang_disposeString(CategoryName
);
171 return createCXString(Out
.str(), true);
174 unsigned clang_defaultDiagnosticDisplayOptions() {
175 return CXDiagnostic_DisplaySourceLocation
| CXDiagnostic_DisplayColumn
|
176 CXDiagnostic_DisplayOption
;
179 enum CXDiagnosticSeverity
clang_getDiagnosticSeverity(CXDiagnostic Diag
) {
180 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
182 return CXDiagnostic_Ignored
;
184 switch (StoredDiag
->Diag
.getLevel()) {
185 case Diagnostic::Ignored
: return CXDiagnostic_Ignored
;
186 case Diagnostic::Note
: return CXDiagnostic_Note
;
187 case Diagnostic::Warning
: return CXDiagnostic_Warning
;
188 case Diagnostic::Error
: return CXDiagnostic_Error
;
189 case Diagnostic::Fatal
: return CXDiagnostic_Fatal
;
192 llvm_unreachable("Invalid diagnostic level");
193 return CXDiagnostic_Ignored
;
196 CXSourceLocation
clang_getDiagnosticLocation(CXDiagnostic Diag
) {
197 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
198 if (!StoredDiag
|| StoredDiag
->Diag
.getLocation().isInvalid())
199 return clang_getNullLocation();
201 return translateSourceLocation(StoredDiag
->Diag
.getLocation().getManager(),
202 StoredDiag
->LangOpts
,
203 StoredDiag
->Diag
.getLocation());
206 CXString
clang_getDiagnosticSpelling(CXDiagnostic Diag
) {
207 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
209 return createCXString("");
211 return createCXString(StoredDiag
->Diag
.getMessage(), false);
214 CXString
clang_getDiagnosticOption(CXDiagnostic Diag
, CXString
*Disable
) {
216 *Disable
= createCXString("");
218 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
220 return createCXString("");
222 unsigned ID
= StoredDiag
->Diag
.getID();
223 if (const char *Option
= DiagnosticIDs::getWarningOptionForDiag(ID
)) {
225 *Disable
= createCXString((llvm::Twine("-Wno-") + Option
).str());
226 return createCXString((llvm::Twine("-W") + Option
).str());
229 if (ID
== diag::fatal_too_many_errors
) {
231 *Disable
= createCXString("-ferror-limit=0");
232 return createCXString("-ferror-limit=");
235 bool EnabledByDefault
;
236 if (DiagnosticIDs::isBuiltinExtensionDiag(ID
, EnabledByDefault
) &&
238 return createCXString("-pedantic");
240 return createCXString("");
243 unsigned clang_getDiagnosticCategory(CXDiagnostic Diag
) {
244 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
248 return DiagnosticIDs::getCategoryNumberForDiag(StoredDiag
->Diag
.getID());
251 CXString
clang_getDiagnosticCategoryName(unsigned Category
) {
252 return createCXString(DiagnosticIDs::getCategoryNameFromID(Category
));
255 unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag
) {
256 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
257 if (!StoredDiag
|| StoredDiag
->Diag
.getLocation().isInvalid())
260 return StoredDiag
->Diag
.range_size();
263 CXSourceRange
clang_getDiagnosticRange(CXDiagnostic Diag
, unsigned Range
) {
264 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
265 if (!StoredDiag
|| Range
>= StoredDiag
->Diag
.range_size() ||
266 StoredDiag
->Diag
.getLocation().isInvalid())
267 return clang_getNullRange();
269 return translateSourceRange(StoredDiag
->Diag
.getLocation().getManager(),
270 StoredDiag
->LangOpts
,
271 StoredDiag
->Diag
.range_begin()[Range
]);
274 unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag
) {
275 CXStoredDiagnostic
*StoredDiag
= static_cast<CXStoredDiagnostic
*>(Diag
);
279 return StoredDiag
->Diag
.fixit_size();
282 CXString
clang_getDiagnosticFixIt(CXDiagnostic Diagnostic
, unsigned FixIt
,
283 CXSourceRange
*ReplacementRange
) {
284 CXStoredDiagnostic
*StoredDiag
285 = static_cast<CXStoredDiagnostic
*>(Diagnostic
);
286 if (!StoredDiag
|| FixIt
>= StoredDiag
->Diag
.fixit_size() ||
287 StoredDiag
->Diag
.getLocation().isInvalid()) {
288 if (ReplacementRange
)
289 *ReplacementRange
= clang_getNullRange();
291 return createCXString("");
294 const FixItHint
&Hint
= StoredDiag
->Diag
.fixit_begin()[FixIt
];
295 if (ReplacementRange
) {
296 // Create a range that covers the entire replacement (or
297 // removal) range, adjusting the end of the range to point to
298 // the end of the token.
300 = translateSourceRange(StoredDiag
->Diag
.getLocation().getManager(),
301 StoredDiag
->LangOpts
,
305 return createCXString(Hint
.CodeToInsert
);