This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- basic/Diagnostic.cpp ---------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2008-2009, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "comma/basic/Diagnostic.h" 00010 #include "comma/basic/TextProvider.h" 00011 00012 #include <cassert> 00013 00014 using namespace comma; 00015 00016 DiagnosticStream::DiagnosticStream(llvm::raw_ostream &stream) 00017 : stream(stream), position(0), message(buffer) { } 00018 00019 DiagnosticStream::~DiagnosticStream() 00020 { 00021 // If the stream was initialized, ensure that it was driven to completion. 00022 assert(position == 0 && "Diagnostic not driven to completion!"); 00023 } 00024 00025 void DiagnosticStream::emitSourceLocation(const SourceLocation &sloc) 00026 { 00027 std::string identity = sloc.getTextProvider()->getIdentity(); 00028 if (!identity.empty()) 00029 message << identity << ":"; 00030 message << sloc.getLine() << ":" << sloc.getColumn(); 00031 } 00032 00033 DiagnosticStream &DiagnosticStream::initialize(const SourceLocation &sloc, 00034 const char *format, 00035 diag::Type type) 00036 { 00037 assert(position == 0 && "Diagnostic reinitialized before completion!"); 00038 00039 sourceLoc = sloc; 00040 buffer.clear(); 00041 this->format = format; 00042 this->type = type; 00043 00044 emitSourceLocation(sloc); 00045 message << ": "; 00046 emitDiagnosticType(type); 00047 message << ": "; 00048 00049 emitFormatComponent(); 00050 return *this; 00051 } 00052 00053 void DiagnosticStream::emitDiagnosticType(diag::Type type) 00054 { 00055 switch (type) { 00056 case diag::ERROR: 00057 message << "error"; 00058 break; 00059 case diag::WARNING: 00060 message << "warning"; 00061 break; 00062 case diag::NOTE: 00063 message << "note"; 00064 break; 00065 } 00066 } 00067 00068 void DiagnosticStream::emitFormatComponent() 00069 { 00070 for (char c = format[position]; c; c = format[++position]) { 00071 if (c == '%') { 00072 c = format[++position]; 00073 assert(c != 0 && "Malformed diagnostic format string!"); 00074 if (c == '%') { 00075 message << c; 00076 continue; 00077 } 00078 ++position; 00079 return; 00080 } 00081 message << c; 00082 } 00083 00084 // If we get here, the format string is exhausted. Print the message and, 00085 // if we are not processing a note, extract the associated line of source 00086 // text and display a caret diagnostic. To ensure that diagnostics print 00087 // properly, strip the source line of any trailing newlines. 00088 stream << message.str() << '\n'; 00089 00090 if (type != diag::NOTE) { 00091 std::string source = sourceLoc.getTextProvider()->extract(sourceLoc); 00092 unsigned column = sourceLoc.getColumn(); 00093 size_t endLoc = source.find('\n'); 00094 if (endLoc != std::string::npos) 00095 source.erase(endLoc); 00096 00097 stream << " " << source << '\n'; 00098 stream << " " << std::string(column, '.') << "^\n"; 00099 } 00100 00101 // Reset the stream. 00102 position = 0; 00103 buffer.clear(); 00104 } 00105 00106 DiagnosticStream &DiagnosticStream::operator<<(const std::string &string) 00107 { 00108 message << string; 00109 emitFormatComponent(); 00110 return *this; 00111 } 00112 00113 DiagnosticStream &DiagnosticStream::operator<<(const char *string) 00114 { 00115 message << string; 00116 emitFormatComponent(); 00117 return *this; 00118 } 00119 00120 DiagnosticStream &DiagnosticStream::operator<<(int n) 00121 { 00122 message << n; 00123 emitFormatComponent(); 00124 return *this; 00125 } 00126 00127 DiagnosticStream &DiagnosticStream::operator<<(char c) 00128 { 00129 message << c; 00130 emitFormatComponent(); 00131 return *this; 00132 } 00133 00134 DiagnosticStream &DiagnosticStream::operator<<(const SourceLocation &sloc) 00135 { 00136 emitSourceLocation(sloc); 00137 emitFormatComponent(); 00138 return *this; 00139 } 00140 00141 DiagnosticStream &DiagnosticStream::operator<<(const IdentifierInfo *idInfo) 00142 { 00143 message << idInfo->getString(); 00144 emitFormatComponent(); 00145 return *this; 00146 } 00147 00148 DiagnosticStream &DiagnosticStream::operator<<(PM::ParameterMode mode) 00149 { 00150 switch (mode) { 00151 default: 00152 assert(false && "Bad parameter mode!"); 00153 break; 00154 00155 case PM::MODE_DEFAULT: 00156 case PM::MODE_IN: 00157 message << "in"; 00158 break; 00159 00160 case PM::MODE_OUT: 00161 message << "out"; 00162 break; 00163 00164 case PM::MODE_IN_OUT: 00165 message << "in out"; 00166 break; 00167 } 00168 emitFormatComponent(); 00169 return *this; 00170 } 00171 00172 DiagnosticStream &DiagnosticStream::operator<<(const DiagnosticComponent &DC) 00173 { 00174 DC.print(message); 00175 emitFormatComponent(); 00176 return *this; 00177 } 00178 00179 //===----------------------------------------------------------------------===// 00180 // Diagnostic 00181 00182 DiagnosticStream &Diagnostic::report(const SourceLocation &loc, diag::Kind kind) 00183 { 00184 diag::Type type = getType(kind); 00185 00186 switch (type) { 00187 case diag::ERROR: 00188 errorCount++; 00189 break; 00190 case diag::WARNING: 00191 warningCount++; 00192 break; 00193 case diag::NOTE: 00194 noteCount++; 00195 break; 00196 } 00197 00198 return diagstream.initialize(loc, getFormat(kind), type); 00199 } 00200 00201 diag::Type Diagnostic::getType(diag::Kind kind) 00202 { 00203 return diagnostics[kind].type; 00204 } 00205 00206 const char *Diagnostic::getFormat(diag::Kind kind) 00207 { 00208 return diagnostics[kind].format; 00209 } 00210 00211 const Diagnostic::DiagInfo 00212 Diagnostic::diagnostics[diag::LAST_UNUSED_DIAGNOSTIC_KIND] = { 00213 00214 #define DIAGNOSTIC(ENUM, TYPE, FORMAT) { FORMAT, diag::TYPE }, 00215 #include "comma/basic/Diagnostic.def" 00216 #undef DIAGNOSTIC 00217 00218 };