blob: 0766548418ebded2b5c198ab9eb126672ae6aa52 [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
Benjamin Kramerb846deb2010-04-12 19:45:50 +000017#include "clang/Frontend/ASTUnit.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000018#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000019#include "llvm/ADT/SmallString.h"
Douglas Gregora88084b2010-02-18 18:08:43 +000020#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000021#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000022#include "llvm/Support/raw_ostream.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000023
Douglas Gregor5352ac02010-01-28 00:27:43 +000024using namespace clang;
25using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000026using namespace clang::cxstring;
Douglas Gregora88084b2010-02-18 18:08:43 +000027using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000028
29//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000030// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000031//-----------------------------------------------------------------------------
32extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000033
Douglas Gregora88084b2010-02-18 18:08:43 +000034unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
35 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
Douglas Gregor405634b2010-04-05 18:10:21 +000036 return CXXUnit? CXXUnit->stored_diag_size() : 0;
Douglas Gregora88084b2010-02-18 18:08:43 +000037}
38
39CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
40 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
Douglas Gregor405634b2010-04-05 18:10:21 +000041 if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
Douglas Gregora88084b2010-02-18 18:08:43 +000042 return 0;
43
Douglas Gregor405634b2010-04-05 18:10:21 +000044 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
Douglas Gregora88084b2010-02-18 18:08:43 +000045 CXXUnit->getASTContext().getLangOptions());
46}
47
48void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
49 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
50 delete Stored;
51}
52
Douglas Gregor274f1902010-02-22 23:17:23 +000053CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
54 if (!Diagnostic)
55 return createCXString("");
Douglas Gregor0a812cf2010-02-18 23:07:20 +000056
57 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
58
Douglas Gregor274f1902010-02-22 23:17:23 +000059 llvm::SmallString<256> Str;
60 llvm::raw_svector_ostream Out(Str);
61
Douglas Gregor0a812cf2010-02-18 23:07:20 +000062 if (Options & CXDiagnostic_DisplaySourceLocation) {
63 // Print source location (file:line), along with optional column
64 // and source ranges.
65 CXFile File;
66 unsigned Line, Column;
Douglas Gregor27a31fe2010-11-09 05:52:02 +000067 clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
68 &File, &Line, &Column, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000069 if (File) {
70 CXString FName = clang_getFileName(File);
Douglas Gregor274f1902010-02-22 23:17:23 +000071 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000072 clang_disposeString(FName);
73 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregor274f1902010-02-22 23:17:23 +000074 Out << Column << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000075
76 if (Options & CXDiagnostic_DisplaySourceRanges) {
77 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
78 bool PrintedRange = false;
79 for (unsigned I = 0; I != N; ++I) {
80 CXFile StartFile, EndFile;
81 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
82
83 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregor27a31fe2010-11-09 05:52:02 +000084 clang_getInstantiationLocation(clang_getRangeStart(Range),
85 &StartFile, &StartLine, &StartColumn,
86 0);
87 clang_getInstantiationLocation(clang_getRangeEnd(Range),
88 &EndFile, &EndLine, &EndColumn, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000089
90 if (StartFile != EndFile || StartFile != File)
91 continue;
92
Douglas Gregor274f1902010-02-22 23:17:23 +000093 Out << "{" << StartLine << ":" << StartColumn << "-"
94 << EndLine << ":" << EndColumn << "}";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000095 PrintedRange = true;
96 }
97 if (PrintedRange)
Douglas Gregor274f1902010-02-22 23:17:23 +000098 Out << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000099 }
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000100
101 Out << " ";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000102 }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000103 }
104
105 /* Print warning/error/etc. */
106 switch (Severity) {
107 case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
Douglas Gregor274f1902010-02-22 23:17:23 +0000108 case CXDiagnostic_Note: Out << "note: "; break;
109 case CXDiagnostic_Warning: Out << "warning: "; break;
110 case CXDiagnostic_Error: Out << "error: "; break;
111 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000112 }
113
114 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
115 if (clang_getCString(Text))
Douglas Gregor274f1902010-02-22 23:17:23 +0000116 Out << clang_getCString(Text);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000117 else
Douglas Gregor274f1902010-02-22 23:17:23 +0000118 Out << "<no diagnostic text>";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000119 clang_disposeString(Text);
Douglas Gregor274f1902010-02-22 23:17:23 +0000120 return createCXString(Out.str(), true);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000121}
122
123unsigned clang_defaultDiagnosticDisplayOptions() {
124 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn;
125}
126
Douglas Gregor5352ac02010-01-28 00:27:43 +0000127enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
128 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
129 if (!StoredDiag)
130 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000131
Douglas Gregora88084b2010-02-18 18:08:43 +0000132 switch (StoredDiag->Diag.getLevel()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000133 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
134 case Diagnostic::Note: return CXDiagnostic_Note;
135 case Diagnostic::Warning: return CXDiagnostic_Warning;
136 case Diagnostic::Error: return CXDiagnostic_Error;
137 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
138 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000139
Douglas Gregor5352ac02010-01-28 00:27:43 +0000140 llvm_unreachable("Invalid diagnostic level");
141 return CXDiagnostic_Ignored;
142}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000143
Douglas Gregor5352ac02010-01-28 00:27:43 +0000144CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
145 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000146 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000147 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000148
Douglas Gregora88084b2010-02-18 18:08:43 +0000149 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
150 StoredDiag->LangOpts,
151 StoredDiag->Diag.getLocation());
Douglas Gregor5352ac02010-01-28 00:27:43 +0000152}
153
154CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
155 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
156 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000157 return createCXString("");
158
Douglas Gregora88084b2010-02-18 18:08:43 +0000159 return createCXString(StoredDiag->Diag.getMessage(), false);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000160}
161
Douglas Gregora3890ba2010-02-08 23:11:56 +0000162unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000163 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000164 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000165 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000166
Douglas Gregora88084b2010-02-18 18:08:43 +0000167 return StoredDiag->Diag.range_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000168}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000169
Douglas Gregora3890ba2010-02-08 23:11:56 +0000170CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
171 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000172 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
173 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000174 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000175
Douglas Gregora88084b2010-02-18 18:08:43 +0000176 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
177 StoredDiag->LangOpts,
178 StoredDiag->Diag.range_begin()[Range]);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000179}
180
181unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
182 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
183 if (!StoredDiag)
184 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000185
Douglas Gregora88084b2010-02-18 18:08:43 +0000186 return StoredDiag->Diag.fixit_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000187}
188
Douglas Gregor473d7012010-02-19 18:16:06 +0000189CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
190 CXSourceRange *ReplacementRange) {
191 CXStoredDiagnostic *StoredDiag
192 = static_cast<CXStoredDiagnostic *>(Diagnostic);
Douglas Gregora88084b2010-02-18 18:08:43 +0000193 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
194 StoredDiag->Diag.getLocation().isInvalid()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000195 if (ReplacementRange)
196 *ReplacementRange = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000197
198 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000199 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000200
Douglas Gregor849b2432010-03-31 17:46:05 +0000201 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor473d7012010-02-19 18:16:06 +0000202 if (ReplacementRange) {
Douglas Gregor783c56f2010-08-18 14:24:02 +0000203 // Create a range that covers the entire replacement (or
204 // removal) range, adjusting the end of the range to point to
205 // the end of the token.
206 *ReplacementRange
207 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
208 StoredDiag->LangOpts,
209 Hint.RemoveRange);
Douglas Gregor473d7012010-02-19 18:16:06 +0000210 }
211
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000212 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000213}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000214
Douglas Gregor5352ac02010-01-28 00:27:43 +0000215} // end extern "C"