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