CIndexDiagnostic.cpp revision 4cd912aa94656697a44c3ebb159f05060300524e
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*                                                                            *|
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*                     The LLVM Compiler Infrastructure                       *|
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*                                                                            *|
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|* This file is distributed under the University of Illinois Open Source      *|
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|* License. See LICENSE.TXT for details.                                      *|
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*                                                                            *|
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*===----------------------------------------------------------------------===*|
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*                                                                            *|
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|* Implements the diagnostic functions of the Clang C interface.              *|
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)|*                                                                            *|
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)\*===----------------------------------------------------------------------===*/
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "CIndexDiagnostic.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "CIndexer.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "CXSourceLocation.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "clang/Frontend/ASTUnit.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "clang/Frontend/FrontendDiagnostic.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/ADT/SmallString.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/ADT/Twine.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Support/MemoryBuffer.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Support/raw_ostream.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace clang;
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace clang::cxloc;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace clang::cxstring;
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using namespace llvm;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//-----------------------------------------------------------------------------
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// C Interface Routines
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//-----------------------------------------------------------------------------
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern "C" {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return CXXUnit? CXXUnit->stored_diag_size() : 0;
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return 0;
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                CXXUnit->getASTContext().getLangOptions());
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delete Stored;
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!Diagnostic)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return createCXString("");
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  llvm::SmallString<256> Str;
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  llvm::raw_svector_ostream Out(Str);
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (Options & CXDiagnostic_DisplaySourceLocation) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Print source location (file:line), along with optional column
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // and source ranges.
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CXFile File;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    unsigned Line, Column;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   &File, &Line, &Column, 0);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (File) {
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CXString FName = clang_getFileName(File);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Out << clang_getCString(FName) << ":" << Line << ":";
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      clang_disposeString(FName);
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (Options & CXDiagnostic_DisplayColumn)
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        Out << Column << ":";
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (Options & CXDiagnostic_DisplaySourceRanges) {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bool PrintedRange = false;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for (unsigned I = 0; I != N; ++I) {
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          CXFile StartFile, EndFile;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          unsigned StartLine, StartColumn, EndLine, EndColumn;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          clang_getInstantiationLocation(clang_getRangeStart(Range),
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         &StartFile, &StartLine, &StartColumn,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         0);
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          clang_getInstantiationLocation(clang_getRangeEnd(Range),
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         &EndFile, &EndLine, &EndColumn, 0);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          if (StartFile != EndFile || StartFile != File)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            continue;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          Out << "{" << StartLine << ":" << StartColumn << "-"
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              << EndLine << ":" << EndColumn << "}";
95          PrintedRange = true;
96        }
97        if (PrintedRange)
98          Out << ":";
99      }
100
101      Out << " ";
102    }
103  }
104
105  /* Print warning/error/etc. */
106  switch (Severity) {
107  case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
108  case CXDiagnostic_Note: Out << "note: "; break;
109  case CXDiagnostic_Warning: Out << "warning: "; break;
110  case CXDiagnostic_Error: Out << "error: "; break;
111  case CXDiagnostic_Fatal: Out << "fatal error: "; break;
112  }
113
114  CXString Text = clang_getDiagnosticSpelling(Diagnostic);
115  if (clang_getCString(Text))
116    Out << clang_getCString(Text);
117  else
118    Out << "<no diagnostic text>";
119  clang_disposeString(Text);
120  return createCXString(Out.str(), true);
121}
122
123unsigned clang_defaultDiagnosticDisplayOptions() {
124  return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn;
125}
126
127enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
128  CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
129  if (!StoredDiag)
130    return CXDiagnostic_Ignored;
131
132  switch (StoredDiag->Diag.getLevel()) {
133  case Diagnostic::Ignored: return CXDiagnostic_Ignored;
134  case Diagnostic::Note:    return CXDiagnostic_Note;
135  case Diagnostic::Warning: return CXDiagnostic_Warning;
136  case Diagnostic::Error:   return CXDiagnostic_Error;
137  case Diagnostic::Fatal:   return CXDiagnostic_Fatal;
138  }
139
140  llvm_unreachable("Invalid diagnostic level");
141  return CXDiagnostic_Ignored;
142}
143
144CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
145  CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
146  if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
147    return clang_getNullLocation();
148
149  return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
150                                 StoredDiag->LangOpts,
151                                 StoredDiag->Diag.getLocation());
152}
153
154CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
155  CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
156  if (!StoredDiag)
157    return createCXString("");
158
159  return createCXString(StoredDiag->Diag.getMessage(), false);
160}
161
162unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
163  CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
164  if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
165    return 0;
166
167  return StoredDiag->Diag.range_size();
168}
169
170CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
171  CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
172  if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
173      StoredDiag->Diag.getLocation().isInvalid())
174    return clang_getNullRange();
175
176  return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
177                              StoredDiag->LangOpts,
178                              StoredDiag->Diag.range_begin()[Range]);
179}
180
181unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
182  CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
183  if (!StoredDiag)
184    return 0;
185
186  return StoredDiag->Diag.fixit_size();
187}
188
189CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
190                                  CXSourceRange *ReplacementRange) {
191  CXStoredDiagnostic *StoredDiag
192    = static_cast<CXStoredDiagnostic *>(Diagnostic);
193  if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
194      StoredDiag->Diag.getLocation().isInvalid()) {
195    if (ReplacementRange)
196      *ReplacementRange = clang_getNullRange();
197
198    return createCXString("");
199  }
200
201  const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
202  if (ReplacementRange) {
203    // Create a range that covers the entire replacement (or
204    // removal) range, adjusting the end of the range to point to
205    // the end of the token.
206    *ReplacementRange
207        = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
208                                StoredDiag->LangOpts,
209                                Hint.RemoveRange);
210  }
211
212  return createCXString(Hint.CodeToInsert);
213}
214
215} // end extern "C"
216