blob: 1beb99386359efe203d24e17435f3a140b9a073b [file] [log] [blame]
Douglas Gregor33cdd812010-02-18 18:08:43 +00001/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
Douglas Gregor4f9c3762010-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 Kremenek7df92ae2010-11-17 23:24:11 +000015#include "CXTranslationUnit.h"
Douglas Gregor4f9c3762010-01-28 00:27:43 +000016#include "CXSourceLocation.h"
Ted Kremenek4b4f3692010-11-16 01:56:27 +000017#include "CXString.h"
Douglas Gregor4f9c3762010-01-28 00:27:43 +000018
Benjamin Kramer064414532010-04-12 19:45:50 +000019#include "clang/Frontend/ASTUnit.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000020#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregord770f732010-02-22 23:17:23 +000021#include "llvm/ADT/SmallString.h"
Douglas Gregor33cdd812010-02-18 18:08:43 +000022#include "llvm/ADT/Twine.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000023#include "llvm/Support/MemoryBuffer.h"
Douglas Gregord770f732010-02-22 23:17:23 +000024#include "llvm/Support/raw_ostream.h"
Douglas Gregorac0605e2010-01-28 06:00:51 +000025
Douglas Gregor4f9c3762010-01-28 00:27:43 +000026using namespace clang;
27using namespace clang::cxloc;
Ted Kremenek5cca6eb2010-02-17 00:41:08 +000028using namespace clang::cxstring;
Douglas Gregor33cdd812010-02-18 18:08:43 +000029using namespace llvm;
Douglas Gregor4f9c3762010-01-28 00:27:43 +000030
31//-----------------------------------------------------------------------------
Ted Kremenek5cca6eb2010-02-17 00:41:08 +000032// C Interface Routines
Douglas Gregor4f9c3762010-01-28 00:27:43 +000033//-----------------------------------------------------------------------------
34extern "C" {
Ted Kremenek5cca6eb2010-02-17 00:41:08 +000035
Douglas Gregor33cdd812010-02-18 18:08:43 +000036unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
Ted Kremenek91554282010-11-16 08:15:36 +000037 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregora2433152010-04-05 18:10:21 +000038 return CXXUnit? CXXUnit->stored_diag_size() : 0;
Douglas Gregor33cdd812010-02-18 18:08:43 +000039}
40
41CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
Ted Kremenek91554282010-11-16 08:15:36 +000042 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData);
Douglas Gregora2433152010-04-05 18:10:21 +000043 if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
Douglas Gregor33cdd812010-02-18 18:08:43 +000044 return 0;
45
Douglas Gregora2433152010-04-05 18:10:21 +000046 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
Douglas Gregor33cdd812010-02-18 18:08:43 +000047 CXXUnit->getASTContext().getLangOptions());
48}
49
50void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +000051 delete static_cast<CXDiagnosticImpl *>(Diagnostic);
Douglas Gregor33cdd812010-02-18 18:08:43 +000052}
53
Douglas Gregord770f732010-02-22 23:17:23 +000054CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
55 if (!Diagnostic)
56 return createCXString("");
Douglas Gregor1e21cc72010-02-18 23:07:20 +000057
58 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
59
Douglas Gregord770f732010-02-22 23:17:23 +000060 llvm::SmallString<256> Str;
61 llvm::raw_svector_ostream Out(Str);
62
Douglas Gregor1e21cc72010-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 Gregor229bebd2010-11-09 06:24:54 +000068 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic),
69 &File, &Line, &Column, 0);
Douglas Gregor1e21cc72010-02-18 23:07:20 +000070 if (File) {
71 CXString FName = clang_getFileName(File);
Douglas Gregord770f732010-02-22 23:17:23 +000072 Out << clang_getCString(FName) << ":" << Line << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +000073 clang_disposeString(FName);
74 if (Options & CXDiagnostic_DisplayColumn)
Douglas Gregord770f732010-02-22 23:17:23 +000075 Out << Column << ":";
Douglas Gregor1e21cc72010-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 Gregor229bebd2010-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 Gregor1e21cc72010-02-18 23:07:20 +000090
91 if (StartFile != EndFile || StartFile != File)
92 continue;
93
Douglas Gregord770f732010-02-22 23:17:23 +000094 Out << "{" << StartLine << ":" << StartColumn << "-"
95 << EndLine << ":" << EndColumn << "}";
Douglas Gregor1e21cc72010-02-18 23:07:20 +000096 PrintedRange = true;
97 }
98 if (PrintedRange)
Douglas Gregord770f732010-02-22 23:17:23 +000099 Out << ":";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000100 }
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000101
102 Out << " ";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000103 }
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000104 }
105
106 /* Print warning/error/etc. */
107 switch (Severity) {
David Blaikieaa347f92011-09-23 20:26:49 +0000108 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
Douglas Gregord770f732010-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 Gregor1e21cc72010-02-18 23:07:20 +0000113 }
114
115 CXString Text = clang_getDiagnosticSpelling(Diagnostic);
116 if (clang_getCString(Text))
Douglas Gregord770f732010-02-22 23:17:23 +0000117 Out << clang_getCString(Text);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000118 else
Douglas Gregord770f732010-02-22 23:17:23 +0000119 Out << "<no diagnostic text>";
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000120 clang_disposeString(Text);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000121
122 if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId |
123 CXDiagnostic_DisplayCategoryName)) {
124 bool NeedBracket = true;
125 bool NeedComma = false;
126
127 if (Options & CXDiagnostic_DisplayOption) {
128 CXString OptionName = clang_getDiagnosticOption(Diagnostic, 0);
129 if (const char *OptionText = clang_getCString(OptionName)) {
130 if (OptionText[0]) {
131 Out << " [" << OptionText;
132 NeedBracket = false;
133 NeedComma = true;
134 }
135 }
136 clang_disposeString(OptionName);
137 }
138
139 if (Options & (CXDiagnostic_DisplayCategoryId |
140 CXDiagnostic_DisplayCategoryName)) {
141 if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) {
142 if (Options & CXDiagnostic_DisplayCategoryId) {
143 if (NeedBracket)
144 Out << " [";
145 if (NeedComma)
146 Out << ", ";
147 Out << CategoryID;
148 NeedBracket = false;
149 NeedComma = true;
150 }
151
152 if (Options & CXDiagnostic_DisplayCategoryName) {
153 CXString CategoryName = clang_getDiagnosticCategoryName(CategoryID);
154 if (NeedBracket)
155 Out << " [";
156 if (NeedComma)
157 Out << ", ";
158 Out << clang_getCString(CategoryName);
159 NeedBracket = false;
160 NeedComma = true;
161 clang_disposeString(CategoryName);
162 }
163 }
164 }
165
166 if (!NeedBracket)
167 Out << "]";
168 }
169
Douglas Gregord770f732010-02-22 23:17:23 +0000170 return createCXString(Out.str(), true);
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000171}
172
173unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregora750e8e2010-11-19 16:18:16 +0000174 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
175 CXDiagnostic_DisplayOption;
Douglas Gregor1e21cc72010-02-18 23:07:20 +0000176}
177
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000178enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000179 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
180 return D->getSeverity();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000181 return CXDiagnostic_Ignored;
182}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000183
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000184CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000185 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
186 return D->getLocation();
187 return clang_getNullLocation();
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000188}
189
190CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000191 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
192 return D->getSpelling();
193 return createCXString("");
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000194}
195
Douglas Gregora750e8e2010-11-19 16:18:16 +0000196CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
197 if (Disable)
198 *Disable = createCXString("");
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000199
200 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
201 return D->getDiagnosticOption(Disable);
Douglas Gregora750e8e2010-11-19 16:18:16 +0000202
203 return createCXString("");
204}
205
206unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000207 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
208 return D->getCategory();
209 return 0;
Douglas Gregora750e8e2010-11-19 16:18:16 +0000210}
211
212CXString clang_getDiagnosticCategoryName(unsigned Category) {
213 return createCXString(DiagnosticIDs::getCategoryNameFromID(Category));
214}
215
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000216unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000217 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
218 return D->getNumRanges();
219 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000220}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000221
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000222CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000223 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
224 if (!D || Range >= D->getNumRanges())
Douglas Gregor4b8fd6d2010-02-08 23:11:56 +0000225 return clang_getNullRange();
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000226 return D->getRange(Range);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000227}
228
229unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000230 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
231 return D->getNumFixIts();
232 return 0;
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000233}
234
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000235CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor836ec942010-02-19 18:16:06 +0000236 CXSourceRange *ReplacementRange) {
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000237 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
238 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor836ec942010-02-19 18:16:06 +0000239 if (ReplacementRange)
240 *ReplacementRange = clang_getNullRange();
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000241 return createCXString("");
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000242 }
Ted Kremenekbb2c7102011-10-31 21:40:19 +0000243 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000244}
Ted Kremenek5cca6eb2010-02-17 00:41:08 +0000245
Douglas Gregor4f9c3762010-01-28 00:27:43 +0000246} // end extern "C"