// cc_err.h see license.txt for copyright and terms of use // objects for representing errors in C++ code #ifndef CC_ERR_H #define CC_ERR_H #include "macros.h" // ENUM_BITWISE_OR #include "str.h" // string #include "srcloc.h" // SourceLoc #include // ostream // flags on errors enum ErrorFlags { // ordinary error EF_NONE = 0x00, // informative, but not an error; typically, such messages should // have a switch to disable them EF_WARNING = 0x01, // This flag means the error will not be supressed in template code. // Most errors inside templates are suppressed since they may be due // to having incomplete information; but an EF_STRONG error is one // where we are sure that the code really is invalid. In theory, as // cppstd does not require diagnosis of errors in uninstantiated // template code, changing an EF_STRONG to EF_NONE should not cause // Elsa to become nonconformant, merely less convenient. Nevertheless, // some of our regression tests contain (intentional) errors that are // diagnosed only because of EF_STRONG. // // 2005-08-08: Removed EF_STRONG_WARNING, replacing uses of it with // EF_STRONG|EF_WARNING instead. EF_STRONG = 0x02, // when this is true, the error message should be considered // when disambiguation; when it's false, it's not a sufficiently // severe error to warrant discarding an ambiguous alternative; // for the most part, only environment lookup failures are // considered to disambiguate EF_DISAMBIGUATES = 0x04, // This flag means this error arose during an attempt to tcheck an // alternative that might not be the correct interpretation, and // during that attempt, an x_assert was raised. Consequently, the // presence of this error message in the error list *cannot* be // used to justify reducing the severity of the x_assert. EF_FROM_DISAMB = 0x08, // This flag means the error arose during type checking of an // uninstantiated template body. In permissive mode, such messages // are turned into warnings. EF_FROM_TEMPLATE = 0x10, // When an error is turned into a warning due to permissive mode, // this flag is set; i.e., it would have been an error in strict // mode. EF_STRICT_ERROR = 0x20, EF_ALL = 0x3F }; ENUM_BITWISE_OPS(ErrorFlags, EF_ALL) // an error message from the typechecker; I plan to expand // this to contain lots of information about the error, but // for now it's just a string like every other typechecker // produces class ErrorMsg { public: SourceLoc loc; // where the error happened string msg; // english explanation ErrorFlags flags; // various // string of instantiation locations leading to the error; if // no instantiations are involved, this should be "", which does // not require any allocation to store (you can also pass NULL // to mean "") string instLoc; public: ErrorMsg(SourceLoc L, rostring m, ErrorFlags f) : loc(L), msg(m), flags(f), instLoc() {} ErrorMsg(SourceLoc L, rostring m, ErrorFlags f, rostring i) : loc(L), msg(m), flags(f), instLoc(i) {} ~ErrorMsg(); bool isWarning() const { return !!(flags & EF_WARNING); } bool disambiguates() const { return !!(flags & EF_DISAMBIGUATES); } string toString() const; }; // list of errors; a reference to this will be passed to functions // that want to report errors to the user class ErrorList { private: // the error objects are actually stored in reverse order, such // that (effectively) appending is fast and prepending is slow; // this field is private because I want to isolate knowledge of // this reverse ordering ObjList list; public: ErrorList(); // empty list initially virtual/*...*/ ~ErrorList(); // deallocates error objects // add an error to the end of list (actually the beginning of // 'list', but clients don't know that, nor should they care) virtual void addError(ErrorMsg * /*owner*/ obj); // add an error to the beginning; this is unusual, and generally // should only be done when it is known that there aren't very // many error objects in the list void prependError(ErrorMsg * /*owner*/ obj); // take all of the error messages in 'src' and (semantically) // append them after messages in 'this'; this operation leaves // 'src' empty, and takes time no more than proportional to the // length of the 'src' list; it's O(1) if 'this' is empty void takeMessages(ErrorList &src); // append // this one takes time proportional to 'this' list void prependMessages(ErrorList &src); // prepend // mark all of the messages with EF_WARNING void markAllAsWarnings(); // mark all with EF_FROM_DISAMB void markAllAsFromDisamb(); // mark with arbitrary flags void markAllWithFlag(ErrorFlags flags); // delete all of the existing messages void deleteAll() { list.deleteAll(); } // keep only messages meeting a specific criteria void filter(bool (*pred)(ErrorMsg *msg)); // various counts of error objects int count() const; // total int numErrors() const; // # that are not EF_WARNING int numWarnings() const; // # that *are* EF_WARNING // number of errors with any flags set in 'flags' int countWithAnyFlag(ErrorFlags flags) const; // true if any are EF_DISAMBIGUATES bool hasDisambErrors() const; bool isEmpty() const { return list.isEmpty(); } // did any of the errors arise from outside a disambiguation process? bool hasFromNonDisambErrors() const; // print all the errors, one per line, in order void print(ostream &os) const; string printToString() const; }; #endif // CC_ERR_H