/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/libclang/CIndexDiagnostic.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- CIndexDiagnostic.cpp - Diagnostics C Interface ---------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // Implements the diagnostic functions of the Clang C interface. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "CIndexDiagnostic.h" |
14 | | #include "CIndexer.h" |
15 | | #include "CXTranslationUnit.h" |
16 | | #include "CXSourceLocation.h" |
17 | | #include "CXString.h" |
18 | | |
19 | | #include "clang/Basic/DiagnosticOptions.h" |
20 | | #include "clang/Frontend/ASTUnit.h" |
21 | | #include "clang/Frontend/DiagnosticRenderer.h" |
22 | | #include "llvm/ADT/SmallString.h" |
23 | | #include "llvm/Support/raw_ostream.h" |
24 | | |
25 | | using namespace clang; |
26 | | using namespace clang::cxloc; |
27 | | using namespace clang::cxdiag; |
28 | | using namespace llvm; |
29 | | |
30 | 2.08k | CXDiagnosticSetImpl::~CXDiagnosticSetImpl() {} |
31 | | |
32 | | void |
33 | 954 | CXDiagnosticSetImpl::appendDiagnostic(std::unique_ptr<CXDiagnosticImpl> D) { |
34 | 954 | Diagnostics.push_back(std::move(D)); |
35 | 954 | } |
36 | | |
37 | 1.58k | CXDiagnosticImpl::~CXDiagnosticImpl() {} |
38 | | |
39 | | namespace { |
40 | | class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl { |
41 | | std::string Message; |
42 | | CXSourceLocation Loc; |
43 | | public: |
44 | | CXDiagnosticCustomNoteImpl(StringRef Msg, CXSourceLocation L) |
45 | | : CXDiagnosticImpl(CustomNoteDiagnosticKind), Message(std::string(Msg)), |
46 | 240 | Loc(L) {} |
47 | | |
48 | 236 | ~CXDiagnosticCustomNoteImpl() override {} |
49 | | |
50 | 464 | CXDiagnosticSeverity getSeverity() const override { |
51 | 464 | return CXDiagnostic_Note; |
52 | 464 | } |
53 | | |
54 | 464 | CXSourceLocation getLocation() const override { return Loc; } |
55 | | |
56 | 232 | CXString getSpelling() const override { |
57 | 232 | return cxstring::createRef(Message.c_str()); |
58 | 232 | } |
59 | | |
60 | 232 | CXString getDiagnosticOption(CXString *Disable) const override { |
61 | 232 | if (Disable) |
62 | 0 | *Disable = cxstring::createEmpty(); |
63 | 232 | return cxstring::createEmpty(); |
64 | 232 | } |
65 | | |
66 | 0 | unsigned getCategory() const override { return 0; } |
67 | 0 | CXString getCategoryText() const override { return cxstring::createEmpty(); } |
68 | | |
69 | 220 | unsigned getNumRanges() const override { return 0; } |
70 | 0 | CXSourceRange getRange(unsigned Range) const override { |
71 | 0 | return clang_getNullRange(); |
72 | 0 | } |
73 | 220 | unsigned getNumFixIts() const override { return 0; } |
74 | | CXString getFixIt(unsigned FixIt, |
75 | 0 | CXSourceRange *ReplacementRange) const override { |
76 | 0 | if (ReplacementRange) |
77 | 0 | *ReplacementRange = clang_getNullRange(); |
78 | 0 | return cxstring::createEmpty(); |
79 | 0 | } |
80 | | }; |
81 | | |
82 | | class CXDiagnosticRenderer : public DiagnosticNoteRenderer { |
83 | | public: |
84 | | CXDiagnosticRenderer(const LangOptions &LangOpts, |
85 | | DiagnosticOptions *DiagOpts, |
86 | | CXDiagnosticSetImpl *mainSet) |
87 | | : DiagnosticNoteRenderer(LangOpts, DiagOpts), |
88 | 493 | CurrentSet(mainSet), MainSet(mainSet) {} |
89 | | |
90 | 493 | ~CXDiagnosticRenderer() override {} |
91 | | |
92 | | void beginDiagnostic(DiagOrStoredDiag D, |
93 | 654 | DiagnosticsEngine::Level Level) override { |
94 | | |
95 | 654 | const StoredDiagnostic *SD = D.dyn_cast<const StoredDiagnostic*>(); |
96 | 654 | if (!SD) |
97 | 16 | return; |
98 | | |
99 | 638 | if (Level != DiagnosticsEngine::Note) |
100 | 414 | CurrentSet = MainSet; |
101 | | |
102 | 638 | auto Owner = std::make_unique<CXStoredDiagnostic>(*SD, LangOpts); |
103 | 638 | CXStoredDiagnostic &CD = *Owner; |
104 | 638 | CurrentSet->appendDiagnostic(std::move(Owner)); |
105 | | |
106 | 638 | if (Level != DiagnosticsEngine::Note) |
107 | 414 | CurrentSet = &CD.getChildDiagnostics(); |
108 | 638 | } |
109 | | |
110 | | void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, |
111 | | DiagnosticsEngine::Level Level, StringRef Message, |
112 | | ArrayRef<CharSourceRange> Ranges, |
113 | 654 | DiagOrStoredDiag D) override { |
114 | 654 | if (!D.isNull()) |
115 | 638 | return; |
116 | | |
117 | 16 | CXSourceLocation L; |
118 | 16 | if (Loc.hasManager()) |
119 | 16 | L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); |
120 | 0 | else |
121 | 0 | L = clang_getNullLocation(); |
122 | 16 | CurrentSet->appendDiagnostic( |
123 | 16 | std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L)); |
124 | 16 | } |
125 | | |
126 | | void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, |
127 | | DiagnosticsEngine::Level Level, |
128 | 0 | ArrayRef<CharSourceRange> Ranges) override {} |
129 | | |
130 | | void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, |
131 | | SmallVectorImpl<CharSourceRange> &Ranges, |
132 | 638 | ArrayRef<FixItHint> Hints) override {} |
133 | | |
134 | 224 | void emitNote(FullSourceLoc Loc, StringRef Message) override { |
135 | 224 | CXSourceLocation L; |
136 | 224 | if (Loc.hasManager()) |
137 | 224 | L = translateSourceLocation(Loc.getManager(), LangOpts, Loc); |
138 | 0 | else |
139 | 0 | L = clang_getNullLocation(); |
140 | 224 | CurrentSet->appendDiagnostic( |
141 | 224 | std::make_unique<CXDiagnosticCustomNoteImpl>(Message, L)); |
142 | 224 | } |
143 | | |
144 | | CXDiagnosticSetImpl *CurrentSet; |
145 | | CXDiagnosticSetImpl *MainSet; |
146 | | }; |
147 | | } |
148 | | |
149 | | CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU, |
150 | 633 | bool checkIfChanged) { |
151 | 633 | ASTUnit *AU = cxtu::getASTUnit(TU); |
152 | | |
153 | 633 | if (TU->Diagnostics && checkIfChanged142 ) { |
154 | | // In normal use, ASTUnit's diagnostics should not change unless we reparse. |
155 | | // Currently they can only change by using the internal testing flag |
156 | | // '-error-on-deserialized-decl' which will error during deserialization of |
157 | | // a declaration. What will happen is: |
158 | | // |
159 | | // -c-index-test gets a CXTranslationUnit |
160 | | // -checks the diagnostics, the diagnostics set is lazily created, |
161 | | // no errors are reported |
162 | | // -later does an operation, like annotation of tokens, that triggers |
163 | | // -error-on-deserialized-decl, that will emit a diagnostic error, |
164 | | // that ASTUnit will catch and add to its stored diagnostics vector. |
165 | | // -c-index-test wants to check whether an error occurred after performing |
166 | | // the operation but can only query the lazily created set. |
167 | | // |
168 | | // We check here if a new diagnostic was appended since the last time the |
169 | | // diagnostic set was created, in which case we reset it. |
170 | | |
171 | 99 | CXDiagnosticSetImpl * |
172 | 99 | Set = static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); |
173 | 99 | if (AU->stored_diag_size() != Set->getNumDiagnostics()) { |
174 | | // Diagnostics in the ASTUnit were updated, reset the associated |
175 | | // diagnostics. |
176 | 2 | delete Set; |
177 | 2 | TU->Diagnostics = nullptr; |
178 | 2 | } |
179 | 99 | } |
180 | | |
181 | 633 | if (!TU->Diagnostics) { |
182 | 493 | CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl(); |
183 | 493 | TU->Diagnostics = Set; |
184 | 493 | IntrusiveRefCntPtr<DiagnosticOptions> DOpts = new DiagnosticOptions; |
185 | 493 | CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(), |
186 | 493 | &*DOpts, Set); |
187 | | |
188 | 493 | for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(), |
189 | 1.13k | ei = AU->stored_diag_end(); it != ei; ++it638 ) { |
190 | 638 | Renderer.emitStoredDiagnostic(*it); |
191 | 638 | } |
192 | 493 | } |
193 | 633 | return static_cast<CXDiagnosticSetImpl*>(TU->Diagnostics); |
194 | 633 | } |
195 | | |
196 | | //----------------------------------------------------------------------------- |
197 | | // C Interface Routines |
198 | | //----------------------------------------------------------------------------- |
199 | 192 | unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) { |
200 | 192 | if (cxtu::isNotUsableTU(Unit)) { |
201 | 0 | LOG_BAD_TU(Unit); |
202 | 0 | return 0; |
203 | 0 | } |
204 | 192 | if (!cxtu::getASTUnit(Unit)) |
205 | 0 | return 0; |
206 | 192 | return lazyCreateDiags(Unit, /*checkIfChanged=*/true)->getNumDiagnostics(); |
207 | 192 | } |
208 | | |
209 | 7 | CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { |
210 | 7 | if (cxtu::isNotUsableTU(Unit)) { |
211 | 0 | LOG_BAD_TU(Unit); |
212 | 0 | return nullptr; |
213 | 0 | } |
214 | | |
215 | 7 | CXDiagnosticSet D = clang_getDiagnosticSetFromTU(Unit); |
216 | 7 | if (!D) |
217 | 0 | return nullptr; |
218 | | |
219 | 7 | CXDiagnosticSetImpl *Diags = static_cast<CXDiagnosticSetImpl*>(D); |
220 | 7 | if (Index >= Diags->getNumDiagnostics()) |
221 | 0 | return nullptr; |
222 | | |
223 | 7 | return Diags->getDiagnostic(Index); |
224 | 7 | } |
225 | | |
226 | 384 | CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit) { |
227 | 384 | if (cxtu::isNotUsableTU(Unit)) { |
228 | 0 | LOG_BAD_TU(Unit); |
229 | 0 | return nullptr; |
230 | 0 | } |
231 | 384 | if (!cxtu::getASTUnit(Unit)) |
232 | 0 | return nullptr; |
233 | 384 | return static_cast<CXDiagnostic>(lazyCreateDiags(Unit)); |
234 | 384 | } |
235 | | |
236 | 212 | void clang_disposeDiagnostic(CXDiagnostic Diagnostic) { |
237 | | // No-op. Kept as a legacy API. CXDiagnostics are now managed |
238 | | // by the enclosing CXDiagnosticSet. |
239 | 212 | } |
240 | | |
241 | 1.49k | CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { |
242 | 1.49k | if (!Diagnostic) |
243 | 0 | return cxstring::createEmpty(); |
244 | | |
245 | 1.49k | CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic); |
246 | | |
247 | 1.49k | SmallString<256> Str; |
248 | 1.49k | llvm::raw_svector_ostream Out(Str); |
249 | | |
250 | 1.49k | if (Options & CXDiagnostic_DisplaySourceLocation) { |
251 | | // Print source location (file:line), along with optional column |
252 | | // and source ranges. |
253 | 1.49k | CXFile File; |
254 | 1.49k | unsigned Line, Column; |
255 | 1.49k | clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), |
256 | 1.49k | &File, &Line, &Column, nullptr); |
257 | 1.49k | if (File) { |
258 | 1.45k | CXString FName = clang_getFileName(File); |
259 | 1.45k | Out << clang_getCString(FName) << ":" << Line << ":"; |
260 | 1.45k | clang_disposeString(FName); |
261 | 1.45k | if (Options & CXDiagnostic_DisplayColumn) |
262 | 1.45k | Out << Column << ":"; |
263 | | |
264 | 1.45k | if (Options & CXDiagnostic_DisplaySourceRanges) { |
265 | 999 | unsigned N = clang_getDiagnosticNumRanges(Diagnostic); |
266 | 999 | bool PrintedRange = false; |
267 | 1.09k | for (unsigned I = 0; I != N; ++I100 ) { |
268 | 100 | CXFile StartFile, EndFile; |
269 | 100 | CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I); |
270 | | |
271 | 100 | unsigned StartLine, StartColumn, EndLine, EndColumn; |
272 | 100 | clang_getSpellingLocation(clang_getRangeStart(Range), |
273 | 100 | &StartFile, &StartLine, &StartColumn, |
274 | 100 | nullptr); |
275 | 100 | clang_getSpellingLocation(clang_getRangeEnd(Range), |
276 | 100 | &EndFile, &EndLine, &EndColumn, nullptr); |
277 | | |
278 | 100 | if (StartFile != EndFile || StartFile != File91 ) |
279 | 26 | continue; |
280 | | |
281 | 74 | Out << "{" << StartLine << ":" << StartColumn << "-" |
282 | 74 | << EndLine << ":" << EndColumn << "}"; |
283 | 74 | PrintedRange = true; |
284 | 74 | } |
285 | 999 | if (PrintedRange) |
286 | 71 | Out << ":"; |
287 | 999 | } |
288 | | |
289 | 1.45k | Out << " "; |
290 | 1.45k | } |
291 | 1.49k | } |
292 | | |
293 | | /* Print warning/error/etc. */ |
294 | 1.49k | switch (Severity) { |
295 | 0 | case CXDiagnostic_Ignored: llvm_unreachable("impossible"); |
296 | 639 | case CXDiagnostic_Note: Out << "note: "; break; |
297 | 340 | case CXDiagnostic_Warning: Out << "warning: "; break; |
298 | 499 | case CXDiagnostic_Error: Out << "error: "; break; |
299 | 12 | case CXDiagnostic_Fatal: Out << "fatal error: "; break; |
300 | 1.49k | } |
301 | | |
302 | 1.49k | CXString Text = clang_getDiagnosticSpelling(Diagnostic); |
303 | 1.49k | if (clang_getCString(Text)) |
304 | 1.49k | Out << clang_getCString(Text); |
305 | 0 | else |
306 | 0 | Out << "<no diagnostic text>"; |
307 | 1.49k | clang_disposeString(Text); |
308 | | |
309 | 1.49k | if (Options & (CXDiagnostic_DisplayOption | CXDiagnostic_DisplayCategoryId | |
310 | 1.49k | CXDiagnostic_DisplayCategoryName)) { |
311 | 1.49k | bool NeedBracket = true; |
312 | 1.49k | bool NeedComma = false; |
313 | | |
314 | 1.49k | if (Options & CXDiagnostic_DisplayOption) { |
315 | 1.49k | CXString OptionName = clang_getDiagnosticOption(Diagnostic, nullptr); |
316 | 1.49k | if (const char *OptionText = clang_getCString(OptionName)) { |
317 | 1.49k | if (OptionText[0]) { |
318 | 337 | Out << " [" << OptionText; |
319 | 337 | NeedBracket = false; |
320 | 337 | NeedComma = true; |
321 | 337 | } |
322 | 1.49k | } |
323 | 1.49k | clang_disposeString(OptionName); |
324 | 1.49k | } |
325 | | |
326 | 1.49k | if (Options & (CXDiagnostic_DisplayCategoryId | |
327 | 0 | CXDiagnostic_DisplayCategoryName)) { |
328 | 0 | if (unsigned CategoryID = clang_getDiagnosticCategory(Diagnostic)) { |
329 | 0 | if (Options & CXDiagnostic_DisplayCategoryId) { |
330 | 0 | if (NeedBracket) |
331 | 0 | Out << " ["; |
332 | 0 | if (NeedComma) |
333 | 0 | Out << ", "; |
334 | 0 | Out << CategoryID; |
335 | 0 | NeedBracket = false; |
336 | 0 | NeedComma = true; |
337 | 0 | } |
338 | | |
339 | 0 | if (Options & CXDiagnostic_DisplayCategoryName) { |
340 | 0 | CXString CategoryName = clang_getDiagnosticCategoryText(Diagnostic); |
341 | 0 | if (NeedBracket) |
342 | 0 | Out << " ["; |
343 | 0 | if (NeedComma) |
344 | 0 | Out << ", "; |
345 | 0 | Out << clang_getCString(CategoryName); |
346 | 0 | NeedBracket = false; |
347 | 0 | NeedComma = true; |
348 | 0 | clang_disposeString(CategoryName); |
349 | 0 | } |
350 | 0 | } |
351 | 0 | } |
352 | | |
353 | 1.49k | (void) NeedComma; // Silence dead store warning. |
354 | 1.49k | if (!NeedBracket) |
355 | 337 | Out << "]"; |
356 | 1.49k | } |
357 | | |
358 | 1.49k | return cxstring::createDup(Out.str()); |
359 | 1.49k | } |
360 | | |
361 | 463 | unsigned clang_defaultDiagnosticDisplayOptions() { |
362 | 463 | return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn | |
363 | 463 | CXDiagnostic_DisplayOption; |
364 | 463 | } |
365 | | |
366 | 2.59k | enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) { |
367 | 2.59k | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag)) |
368 | 2.59k | return D->getSeverity(); |
369 | 0 | return CXDiagnostic_Ignored; |
370 | 0 | } |
371 | | |
372 | 2.59k | CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) { |
373 | 2.59k | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl*>(Diag)) |
374 | 2.59k | return D->getLocation(); |
375 | 0 | return clang_getNullLocation(); |
376 | 0 | } |
377 | | |
378 | 1.56k | CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) { |
379 | 1.56k | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) |
380 | 1.56k | return D->getSpelling(); |
381 | 0 | return cxstring::createEmpty(); |
382 | 0 | } |
383 | | |
384 | 1.56k | CXString clang_getDiagnosticOption(CXDiagnostic Diag, CXString *Disable) { |
385 | 1.56k | if (Disable) |
386 | 0 | *Disable = cxstring::createEmpty(); |
387 | | |
388 | 1.56k | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) |
389 | 1.56k | return D->getDiagnosticOption(Disable); |
390 | | |
391 | 0 | return cxstring::createEmpty(); |
392 | 0 | } |
393 | | |
394 | 0 | unsigned clang_getDiagnosticCategory(CXDiagnostic Diag) { |
395 | 0 | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) |
396 | 0 | return D->getCategory(); |
397 | 0 | return 0; |
398 | 0 | } |
399 | | |
400 | 0 | CXString clang_getDiagnosticCategoryName(unsigned Category) { |
401 | | // Kept for backward compatibility. |
402 | 0 | return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(Category)); |
403 | 0 | } |
404 | | |
405 | 76 | CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) { |
406 | 76 | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) |
407 | 76 | return D->getCategoryText(); |
408 | 0 | return cxstring::createEmpty(); |
409 | 0 | } |
410 | | |
411 | 1.07k | unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) { |
412 | 1.07k | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) |
413 | 1.07k | return D->getNumRanges(); |
414 | 0 | return 0; |
415 | 0 | } |
416 | | |
417 | 136 | CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) { |
418 | 136 | CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag); |
419 | 136 | if (!D || Range >= D->getNumRanges()) |
420 | 0 | return clang_getNullRange(); |
421 | 136 | return D->getRange(Range); |
422 | 136 | } |
423 | | |
424 | 1.07k | unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) { |
425 | 1.07k | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) |
426 | 1.07k | return D->getNumFixIts(); |
427 | 0 | return 0; |
428 | 0 | } |
429 | | |
430 | | CXString clang_getDiagnosticFixIt(CXDiagnostic Diag, unsigned FixIt, |
431 | 49 | CXSourceRange *ReplacementRange) { |
432 | 49 | CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag); |
433 | 49 | if (!D || FixIt >= D->getNumFixIts()) { |
434 | 0 | if (ReplacementRange) |
435 | 0 | *ReplacementRange = clang_getNullRange(); |
436 | 0 | return cxstring::createEmpty(); |
437 | 0 | } |
438 | 49 | return D->getFixIt(FixIt, ReplacementRange); |
439 | 49 | } |
440 | | |
441 | 392 | void clang_disposeDiagnosticSet(CXDiagnosticSet Diags) { |
442 | 392 | if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl *>(Diags)) { |
443 | 392 | if (D->isExternallyManaged()) |
444 | 15 | delete D; |
445 | 392 | } |
446 | 392 | } |
447 | | |
448 | | CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags, |
449 | 930 | unsigned Index) { |
450 | 930 | if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags)) |
451 | 930 | if (Index < D->getNumDiagnostics()) |
452 | 930 | return D->getDiagnostic(Index); |
453 | 0 | return nullptr; |
454 | 0 | } |
455 | | |
456 | 898 | CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic Diag) { |
457 | 898 | if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag)) { |
458 | 898 | CXDiagnosticSetImpl &ChildDiags = D->getChildDiagnostics(); |
459 | 648 | return ChildDiags.empty() ? nullptr : (CXDiagnosticSet) &ChildDiags250 ; |
460 | 898 | } |
461 | 0 | return nullptr; |
462 | 0 | } |
463 | | |
464 | 714 | unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags) { |
465 | 714 | if (CXDiagnosticSetImpl *D = static_cast<CXDiagnosticSetImpl*>(Diags)) |
466 | 714 | return D->getNumDiagnostics(); |
467 | 0 | return 0; |
468 | 0 | } |