blob: 1beb99386359efe203d24e17435f3a140b9a073b [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) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +000051 delete static_cast<CXDiagnosticImpl *>(Diagnostic);
Douglas Gregora88084b2010-02-18 18:08:43 +000052}
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) {
David Blaikieeb2d1f12011-09-23 20:26:49 +0000108 case CXDiagnostic_Ignored: llvm_unreachable("impossible");
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 Gregoraa5f1352010-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 Gregor274f1902010-02-22 23:17:23 +0000170 return createCXString(Out.str(), true);
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000171}
172
173unsigned clang_defaultDiagnosticDisplayOptions() {
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000174 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn |
175 CXDiagnostic_DisplayOption;
Douglas Gregor0a812cf2010-02-18 23:07:20 +0000176}
177
Douglas Gregor5352ac02010-01-28 00:27:43 +0000178enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000179 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
180 return D->getSeverity();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000181 return CXDiagnostic_Ignored;
182}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000183
Douglas Gregor5352ac02010-01-28 00:27:43 +0000184CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000185 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag))
186 return D->getLocation();
187 return clang_getNullLocation();
Douglas Gregor5352ac02010-01-28 00:27:43 +0000188}
189
190CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000191 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
192 return D->getSpelling();
193 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000194}
195
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000196CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) {
197 if (Disable)
198 *Disable = createCXString("");
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000199
200 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
201 return D->getDiagnosticOption(Disable);
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000202
203 return createCXString("");
204}
205
206unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000207 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
208 return D->getCategory();
209 return 0;
Douglas Gregoraa5f1352010-11-19 16:18:16 +0000210}
211
212CXString clang_getDiagnosticCategoryName(unsigned Category) {
213 return createCXString(DiagnosticIDs::getCategoryNameFromID(Category));
214}
215
Douglas Gregora3890ba2010-02-08 23:11:56 +0000216unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000217 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
218 return D->getNumRanges();
219 return 0;
Douglas Gregor5352ac02010-01-28 00:27:43 +0000220}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000221
Douglas Gregora3890ba2010-02-08 23:11:56 +0000222CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000223 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
224 if (!D || Range >= D->getNumRanges())
Douglas Gregora3890ba2010-02-08 23:11:56 +0000225 return clang_getNullRange();
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000226 return D->getRange(Range);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000227}
228
229unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000230 if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
231 return D->getNumFixIts();
232 return 0;
Douglas Gregor5352ac02010-01-28 00:27:43 +0000233}
234
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000235CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt,
Douglas Gregor473d7012010-02-19 18:16:06 +0000236 CXSourceRange *ReplacementRange) {
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000237 CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag);
238 if (!D || FixIt >= D->getNumFixIts()) {
Douglas Gregor473d7012010-02-19 18:16:06 +0000239 if (ReplacementRange)
240 *ReplacementRange = clang_getNullRange();
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000241 return createCXString("");
Douglas Gregor5352ac02010-01-28 00:27:43 +0000242 }
Ted Kremenek1edabbc2011-10-31 21:40:19 +0000243 return D->getFixIt(FixIt, ReplacementRange);
Douglas Gregor5352ac02010-01-28 00:27:43 +0000244}
Ted Kremenekee4db4f2010-02-17 00:41:08 +0000245
Douglas Gregor5352ac02010-01-28 00:27:43 +0000246} // end extern "C"