CIndexDiagnostic.cpp revision 0a90d32523bfe5fa63e11b648686c9699f786d15
1/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\ 2|* *| 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 "CXTranslationUnit.h" 16#include "CXSourceLocation.h" 17#include "CXString.h" 18 19#include "clang/Frontend/ASTUnit.h" 20#include "clang/Frontend/FrontendDiagnostic.h" 21#include "llvm/ADT/SmallString.h" 22#include "llvm/ADT/Twine.h" 23#include "llvm/Support/MemoryBuffer.h" 24#include "llvm/Support/raw_ostream.h" 25 26using namespace clang; 27using namespace clang::cxloc; 28using namespace clang::cxstring; 29using namespace llvm; 30 31//----------------------------------------------------------------------------- 32// C Interface Routines 33//----------------------------------------------------------------------------- 34extern "C" { 35 36unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) { 37 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData); 38 return CXXUnit? CXXUnit->stored_diag_size() : 0; 39} 40 41CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) { 42 ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit->TUData); 43 if (!CXXUnit || Index >= CXXUnit->stored_diag_size()) 44 return 0; 45 46 return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index], 47 CXXUnit->getASTContext().getLangOptions()); 48} 49 50void clang_disposeDiagnostic(CXDiagnostic Diagnostic) { 51 CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic); 52 delete Stored; 53} 54 55CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { 56 if (!Diagnostic) 57 return createCXString(""); 58 59 CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic); 60 61 llvm::SmallString<256> Str; 62 llvm::raw_svector_ostream Out(Str); 63 64 if (Options & CXDiagnostic_DisplaySourceLocation) { 65 // Print source location (file:line), along with optional column 66 // and source ranges. 67 CXFile File; 68 unsigned Line, Column; 69 clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), 70 &File, &Line, &Column, 0); 71 if (File) { 72 CXString FName = clang_getFileName(File); 73 Out << clang_getCString(FName) << ":" << Line << ":"; 74 clang_disposeString(FName); 75 if (Options & CXDiagnostic_DisplayColumn) 76 Out << Column << ":"; 77 78 if (Options & CXDiagnostic_DisplaySourceRanges) { 79 unsigned N = clang_getDiagnosticNumRanges(Diagnostic); 80 bool PrintedRange = false; 81 for (unsigned I = 0; I != N; ++I) { 82 CXFile StartFile, EndFile; 83 CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I); 84 85 unsigned StartLine, StartColumn, EndLine, EndColumn; 86 clang_getSpellingLocation(clang_getRangeStart(Range), 87 &StartFile, &StartLine, &StartColumn, 88 0); 89 clang_getSpellingLocation(clang_getRangeEnd(Range), 90 &EndFile, &EndLine, &EndColumn, 0); 91 92 if (StartFile != EndFile || StartFile != File) 93 continue; 94 95 Out << "{" << StartLine << ":" << StartColumn << "-" 96 << EndLine << ":" << EndColumn << "}"; 97 PrintedRange = true; 98 } 99 if (PrintedRange) 100 Out << ":"; 101 } 102 103 Out << " "; 104 } 105 } 106 107 /* Print warning/error/etc. */ 108 switch (Severity) { 109 case CXDiagnostic_Ignored: assert(0 && "impossible"); break; 110 case CXDiagnostic_Note: Out << "note: "; break; 111 case CXDiagnostic_Warning: Out << "warning: "; break; 112 case CXDiagnostic_Error: Out << "error: "; break; 113 case CXDiagnostic_Fatal: Out << "fatal error: "; break; 114 } 115 116 CXString Text = clang_getDiagnosticSpelling(Diagnostic); 117 if (clang_getCString(Text)) 118 Out << clang_getCString(Text); 119 else 120 Out << "<no diagnostic text>"; 121 clang_disposeString(Text); 122 return createCXString(Out.str(), true); 123} 124 125unsigned clang_defaultDiagnosticDisplayOptions() { 126 return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn; 127} 128 129enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) { 130 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); 131 if (!StoredDiag) 132 return CXDiagnostic_Ignored; 133 134 switch (StoredDiag->Diag.getLevel()) { 135 case Diagnostic::Ignored: return CXDiagnostic_Ignored; 136 case Diagnostic::Note: return CXDiagnostic_Note; 137 case Diagnostic::Warning: return CXDiagnostic_Warning; 138 case Diagnostic::Error: return CXDiagnostic_Error; 139 case Diagnostic::Fatal: return CXDiagnostic_Fatal; 140 } 141 142 llvm_unreachable("Invalid diagnostic level"); 143 return CXDiagnostic_Ignored; 144} 145 146CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) { 147 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); 148 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid()) 149 return clang_getNullLocation(); 150 151 return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(), 152 StoredDiag->LangOpts, 153 StoredDiag->Diag.getLocation()); 154} 155 156CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) { 157 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); 158 if (!StoredDiag) 159 return createCXString(""); 160 161 return createCXString(StoredDiag->Diag.getMessage(), false); 162} 163 164unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) { 165 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); 166 if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid()) 167 return 0; 168 169 return StoredDiag->Diag.range_size(); 170} 171 172CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) { 173 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); 174 if (!StoredDiag || Range >= StoredDiag->Diag.range_size() || 175 StoredDiag->Diag.getLocation().isInvalid()) 176 return clang_getNullRange(); 177 178 return translateSourceRange(StoredDiag->Diag.getLocation().getManager(), 179 StoredDiag->LangOpts, 180 StoredDiag->Diag.range_begin()[Range]); 181} 182 183unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) { 184 CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag); 185 if (!StoredDiag) 186 return 0; 187 188 return StoredDiag->Diag.fixit_size(); 189} 190 191CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt, 192 CXSourceRange *ReplacementRange) { 193 CXStoredDiagnostic *StoredDiag 194 = static_cast<CXStoredDiagnostic *>(Diagnostic); 195 if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() || 196 StoredDiag->Diag.getLocation().isInvalid()) { 197 if (ReplacementRange) 198 *ReplacementRange = clang_getNullRange(); 199 200 return createCXString(""); 201 } 202 203 const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt]; 204 if (ReplacementRange) { 205 // Create a range that covers the entire replacement (or 206 // removal) range, adjusting the end of the range to point to 207 // the end of the token. 208 *ReplacementRange 209 = translateSourceRange(StoredDiag->Diag.getLocation().getManager(), 210 StoredDiag->LangOpts, 211 Hint.RemoveRange); 212 } 213 214 return createCXString(Hint.CodeToInsert); 215} 216 217} // end extern "C" 218