blob: 35acd0da0078b5f30a31c1883cf187665f89dc03 [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"
Ted Kremenek0a90d322010-11-17 23:24:11 +000015#include "CXTranslationUnit.h"
Douglas Gregor5352ac02010-01-28 00:27:43 +000016#include "CXSourceLocation.h"
Ted Kremeneked122732010-11-16 01:56:27 +000017#include "CXString.h"
Douglas Gregor5352ac02010-01-28 00:27:43 +000018
Benjamin Kramerb846deb2010-04-12 19:45:50 +000019#include "clang/Frontend/ASTUnit.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000021#include "llvm/ADT/SmallString.h"
Douglas Gregora88084b2010-02-18 18:08:43 +000022#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000023#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000024#include "llvm/Support/raw_ostream.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000025
Douglas Gregor5352ac02010-01-28 00:27:43 +000026using namespace clang;
27using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000028using namespace clang::cxstring;
Douglas Gregora88084b2010-02-18 18:08:43 +000029using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000030
31//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000032// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000033//-----------------------------------------------------------------------------
34extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000035
Douglas Gregora88084b2010-02-18 18:08:43 +000036unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Ted Kremeneka60ed472010-11-16 08:15:36 +000037 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregor405634b2010-04-05 18:10:21 +000038 return CXXUnit? CXXUnit->stored_diag_size() : 0;
Douglas Gregora88084b2010-02-18 18:08:43 +000039}
40
41CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Ted Kremeneka60ed472010-11-16 08:15:36 +000042 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregor405634b2010-04-05 18:10:21 +000043 if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
Douglas Gregora88084b2010-02-18 18:08:43 +000044 return 0;
45
Douglas Gregor405634b2010-04-05 18:10:21 +000046 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
Douglas Gregora88084b2010-02-18 18:08:43 +000047 CXXUnit->getASTContext().getLangOptions());
48}
49
50void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
51 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
52 delete Stored;
53}
54
Douglas Gregor274f1902010-02-22 23:17:23 +000055CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
56 if (!Diagnostic)
57 return createCXString("");
Douglas Gregor0a812cf2010-02-18 23:07:20 +000058
59 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
60
Douglas Gregor274f1902010-02-22 23:17:23 +000061 llvm::SmallString<256> Str;
62 llvm::raw_svector_ostream Out(Str);
63
Douglas Gregor0a812cf2010-02-18 23:07:20 +000064 if (Options & CXDiagnostic_DisplaySourceLocation) {
65 // Print source location (file:line), along with optional column
66 // and source ranges.
67 CXFile File;
68 unsigned Line, Column;
Douglas Gregora9b06d42010-11-09 06:24:54 +000069 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
70 &File, &Line, &Column, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000071 if (File) {
72 CXString FName = clang_getFileName(File);
Douglas Gregor274f1902010-02-22 23:17:23 +000073 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000074 clang_disposeString(FName);
75 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregor274f1902010-02-22 23:17:23 +000076 Out << Column << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000077
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);
84
85 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregora9b06d42010-11-09 06:24:54 +000086 clang_getSpellingLocation(clang_getRangeStart(Range),
87 &StartFile, &StartLine, &StartColumn,
88 0);
89 clang_getSpellingLocation(clang_getRangeEnd(Range),
90 &EndFile, &EndLine, &EndColumn, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000091
92 if (StartFile != EndFile || StartFile != File)
93 continue;
94
Douglas Gregor274f1902010-02-22 23:17:23 +000095 Out << "{" << StartLine << ":" << StartColumn << "-"
96 << EndLine << ":" << EndColumn << "}";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000097 PrintedRange = true;
98 }
99 if (PrintedRange)
Douglas Gregor274f1902010-02-22 23:17:23 +0000100 Out << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000101 }
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000102
103 Out << " ";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000104 }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000105 }
106
107 /* Print warning/error/etc. */
108 switch (Severity) {
109 case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
Douglas Gregor274f1902010-02-22 23:17:23 +0000110 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;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000114 }
115
116 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
117 if (clang_getCString(Text))
Douglas Gregor274f1902010-02-22 23:17:23 +0000118 Out << clang_getCString(Text);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000119 else
Douglas Gregor274f1902010-02-22 23:17:23 +0000120 Out << "<no diagnostic text>";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000121 clang_disposeString(Text);
Douglas Gregor274f1902010-02-22 23:17:23 +0000122 return createCXString(Out.str(), true);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000123}
124
125unsigned clang_defaultDiagnosticDisplayOptions() {
126 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn;
127}
128
Douglas Gregor5352ac02010-01-28 00:27:43 +0000129enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
130 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
131 if (!StoredDiag)
132 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000133
Douglas Gregora88084b2010-02-18 18:08:43 +0000134 switch (StoredDiag->Diag.getLevel()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000135 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
136 case Diagnostic::Note: return CXDiagnostic_Note;
137 case Diagnostic::Warning: return CXDiagnostic_Warning;
138 case Diagnostic::Error: return CXDiagnostic_Error;
139 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
140 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000141
Douglas Gregor5352ac02010-01-28 00:27:43 +0000142 llvm_unreachable("Invalid diagnostic level");
143 return CXDiagnostic_Ignored;
144}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000145
Douglas Gregor5352ac02010-01-28 00:27:43 +0000146CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
147 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000148 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000149 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000150
Douglas Gregora88084b2010-02-18 18:08:43 +0000151 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
152 StoredDiag->LangOpts,
153 StoredDiag->Diag.getLocation());
Douglas Gregor5352ac02010-01-28 00:27:43 +0000154}
155
156CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
157 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
158 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000159 return createCXString("");
160
Douglas Gregora88084b2010-02-18 18:08:43 +0000161 return createCXString(StoredDiag->Diag.getMessage(), false);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000162}
163
Douglas Gregora3890ba2010-02-08 23:11:56 +0000164unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000165 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000166 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000167 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000168
Douglas Gregora88084b2010-02-18 18:08:43 +0000169 return StoredDiag->Diag.range_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000170}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000171
Douglas Gregora3890ba2010-02-08 23:11:56 +0000172CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
173 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000174 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
175 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000176 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000177
Douglas Gregora88084b2010-02-18 18:08:43 +0000178 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
179 StoredDiag->LangOpts,
180 StoredDiag->Diag.range_begin()[Range]);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000181}
182
183unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
184 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
185 if (!StoredDiag)
186 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000187
Douglas Gregora88084b2010-02-18 18:08:43 +0000188 return StoredDiag->Diag.fixit_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000189}
190
Douglas Gregor473d7012010-02-19 18:16:06 +0000191CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
192 CXSourceRange *ReplacementRange) {
193 CXStoredDiagnostic *StoredDiag
194 = static_cast<CXStoredDiagnostic *>(Diagnostic);
Douglas Gregora88084b2010-02-18 18:08:43 +0000195 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
196 StoredDiag->Diag.getLocation().isInvalid()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000197 if (ReplacementRange)
198 *ReplacementRange = 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 Gregor849b2432010-03-31 17:46:05 +0000203 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor473d7012010-02-19 18:16:06 +0000204 if (ReplacementRange) {
Douglas Gregor783c56f2010-08-18 14:24:02 +0000205 // Create a range that covers the entire replacement (or
206 // removal) range, adjusting the end of the range to point to
207 // the end of the token.
208 *ReplacementRange
209 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
210 StoredDiag->LangOpts,
211 Hint.RemoveRange);
Douglas Gregor473d7012010-02-19 18:16:06 +0000212 }
213
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000214 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000215}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000216
Douglas Gregor5352ac02010-01-28 00:27:43 +0000217} // end extern "C"