00001
00002
00003
00004
00005
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
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
00085
00086
00087
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
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
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 };