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 };