blob: 31ca6791a6e1b3bcab0a48e5cd67abbf020b7c56 [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"
Ted Kremeneked122732010-11-16 01:56:27 +000016#include "CXString.h"
Douglas Gregor5352ac02010-01-28 00:27:43 +000017
Benjamin Kramerb846deb2010-04-12 19:45:50 +000018#include "clang/Frontend/ASTUnit.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000019#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000020#include "llvm/ADT/SmallString.h"
Douglas Gregora88084b2010-02-18 18:08:43 +000021#include "llvm/ADT/Twine.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000022#include "llvm/Support/MemoryBuffer.h"
Douglas Gregor274f1902010-02-22 23:17:23 +000023#include "llvm/Support/raw_ostream.h"
Douglas Gregord93256e2010-01-28 06:00:51 +000024
Douglas Gregor5352ac02010-01-28 00:27:43 +000025using namespace clang;
26using namespace clang::cxloc;
Ted Kremenekee4db4f2010-02-17 00:41:08 +000027using namespace clang::cxstring;
Douglas Gregora88084b2010-02-18 18:08:43 +000028using namespace llvm;
Douglas Gregor5352ac02010-01-28 00:27:43 +000029
30//-----------------------------------------------------------------------------
Ted Kremenekee4db4f2010-02-17 00:41:08 +000031// C Interface Routines
Douglas Gregor5352ac02010-01-28 00:27:43 +000032//-----------------------------------------------------------------------------
33extern "C" {
Ted Kremenekee4db4f2010-02-17 00:41:08 +000034
Douglas Gregora88084b2010-02-18 18:08:43 +000035unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Ted Kremeneka60ed472010-11-16 08:15:36 +000036 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregor405634b2010-04-05 18:10:21 +000037 return CXXUnit? CXXUnit->stored_diag_size() : 0;
Douglas Gregora88084b2010-02-18 18:08:43 +000038}
39
40CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Ted Kremeneka60ed472010-11-16 08:15:36 +000041 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregor405634b2010-04-05 18:10:21 +000042 if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
Douglas Gregora88084b2010-02-18 18:08:43 +000043 return 0;
44
Douglas Gregor405634b2010-04-05 18:10:21 +000045 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
Douglas Gregora88084b2010-02-18 18:08:43 +000046 CXXUnit->getASTContext().getLangOptions());
47}
48
49void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
50 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
51 delete Stored;
52}
53
Douglas Gregor274f1902010-02-22 23:17:23 +000054CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
55 if (!Diagnostic)
56 return createCXString("");
Douglas Gregor0a812cf2010-02-18 23:07:20 +000057
58 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
59
Douglas Gregor274f1902010-02-22 23:17:23 +000060 llvm::SmallString<256> Str;
61 llvm::raw_svector_ostream Out(Str);
62
Douglas Gregor0a812cf2010-02-18 23:07:20 +000063 if (Options & CXDiagnostic_DisplaySourceLocation) {
64 // Print source location (file:line), along with optional column
65 // and source ranges.
66 CXFile File;
67 unsigned Line, Column;
Douglas Gregora9b06d42010-11-09 06:24:54 +000068 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
69 &File, &Line, &Column, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000070 if (File) {
71 CXString FName = clang_getFileName(File);
Douglas Gregor274f1902010-02-22 23:17:23 +000072 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000073 clang_disposeString(FName);
74 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregor274f1902010-02-22 23:17:23 +000075 Out << Column << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000076
77 if (Options & CXDiagnostic_DisplaySourceRanges) {
78 unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
79 bool PrintedRange = false;
80 for (unsigned I = 0; I != N; ++I) {
81 CXFile StartFile, EndFile;
82 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
83
84 unsigned StartLine, StartColumn, EndLine, EndColumn;
Douglas Gregora9b06d42010-11-09 06:24:54 +000085 clang_getSpellingLocation(clang_getRangeStart(Range),
86 &StartFile, &StartLine, &StartColumn,
87 0);
88 clang_getSpellingLocation(clang_getRangeEnd(Range),
89 &EndFile, &EndLine, &EndColumn, 0);
Douglas Gregor0a812cf2010-02-18 23:07:20 +000090
91 if (StartFile != EndFile || StartFile != File)
92 continue;
93
Douglas Gregor274f1902010-02-22 23:17:23 +000094 Out << "{" << StartLine << ":" << StartColumn << "-"
95 << EndLine << ":" << EndColumn << "}";
Douglas Gregor0a812cf2010-02-18 23:07:20 +000096 PrintedRange = true;
97 }
98 if (PrintedRange)
Douglas Gregor274f1902010-02-22 23:17:23 +000099 Out << ":";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000100 }
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000101
102 Out << " ";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000103 }
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000104 }
105
106 /* Print warning/error/etc. */
107 switch (Severity) {
108 case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
Douglas Gregor274f1902010-02-22 23:17:23 +0000109 case CXDiagnostic_Note: Out << "note: "; break;
110 case CXDiagnostic_Warning: Out << "warning: "; break;
111 case CXDiagnostic_Error: Out << "error: "; break;
112 case CXDiagnostic_Fatal: Out << "fatal error: "; break;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000113 }
114
115 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
116 if (clang_getCString(Text))
Douglas Gregor274f1902010-02-22 23:17:23 +0000117 Out << clang_getCString(Text);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000118 else
Douglas Gregor274f1902010-02-22 23:17:23 +0000119 Out << "<no diagnostic text>";
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000120 clang_disposeString(Text);
Douglas Gregor274f1902010-02-22 23:17:23 +0000121 return createCXString(Out.str(), true);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000122}
123
124unsigned clang_defaultDiagnosticDisplayOptions() {
125 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn;
126}
127
Douglas Gregor5352ac02010-01-28 00:27:43 +0000128enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
129 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
130 if (!StoredDiag)
131 return CXDiagnostic_Ignored;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000132
Douglas Gregora88084b2010-02-18 18:08:43 +0000133 switch (StoredDiag->Diag.getLevel()) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000134 case Diagnostic::Ignored: return CXDiagnostic_Ignored;
135 case Diagnostic::Note: return CXDiagnostic_Note;
136 case Diagnostic::Warning: return CXDiagnostic_Warning;
137 case Diagnostic::Error: return CXDiagnostic_Error;
138 case Diagnostic::Fatal: return CXDiagnostic_Fatal;
139 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000140
Douglas Gregor5352ac02010-01-28 00:27:43 +0000141 llvm_unreachable("Invalid diagnostic level");
142 return CXDiagnostic_Ignored;
143}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000144
Douglas Gregor5352ac02010-01-28 00:27:43 +0000145CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
146 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000147 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregor5352ac02010-01-28 00:27:43 +0000148 return clang_getNullLocation();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000149
Douglas Gregora88084b2010-02-18 18:08:43 +0000150 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
151 StoredDiag->LangOpts,
152 StoredDiag->Diag.getLocation());
Douglas Gregor5352ac02010-01-28 00:27:43 +0000153}
154
155CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
156 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
157 if (!StoredDiag)
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000158 return createCXString("");
159
Douglas Gregora88084b2010-02-18 18:08:43 +0000160 return createCXString(StoredDiag->Diag.getMessage(), false);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000161}
162
Douglas Gregora3890ba2010-02-08 23:11:56 +0000163unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Douglas Gregor5352ac02010-01-28 00:27:43 +0000164 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000165 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000166 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000167
Douglas Gregora88084b2010-02-18 18:08:43 +0000168 return StoredDiag->Diag.range_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000169}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000170
Douglas Gregora3890ba2010-02-08 23:11:56 +0000171CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
172 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
Douglas Gregora88084b2010-02-18 18:08:43 +0000173 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
174 StoredDiag->Diag.getLocation().isInvalid())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000175 return clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000176
Douglas Gregora88084b2010-02-18 18:08:43 +0000177 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
178 StoredDiag->LangOpts,
179 StoredDiag->Diag.range_begin()[Range]);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000180}
181
182unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
183 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
184 if (!StoredDiag)
185 return 0;
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000186
Douglas Gregora88084b2010-02-18 18:08:43 +0000187 return StoredDiag->Diag.fixit_size();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000188}
189
Douglas Gregor473d7012010-02-19 18:16:06 +0000190CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
191 CXSourceRange *ReplacementRange) {
192 CXStoredDiagnostic *StoredDiag
193 = static_cast<CXStoredDiagnostic *>(Diagnostic);
Douglas Gregora88084b2010-02-18 18:08:43 +0000194 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
195 StoredDiag->Diag.getLocation().isInvalid()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000196 if (ReplacementRange)
197 *ReplacementRange = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000198
199 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000200 }
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000201
Douglas Gregor849b2432010-03-31 17:46:05 +0000202 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
Douglas Gregor473d7012010-02-19 18:16:06 +0000203 if (ReplacementRange) {
Douglas Gregor783c56f2010-08-18 14:24:02 +0000204 // Create a range that covers the entire replacement (or
205 // removal) range, adjusting the end of the range to point to
206 // the end of the token.
207 *ReplacementRange
208 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
209 StoredDiag->LangOpts,
210 Hint.RemoveRange);
Douglas Gregor473d7012010-02-19 18:16:06 +0000211 }
212
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000213 return createCXString(Hint.CodeToInsert);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000214}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000215
Douglas Gregor5352ac02010-01-28 00:27:43 +0000216} // end extern "C"