Cppcheck
errorlogger.h
Go to the documentation of this file.
00001 /*
00002  * Cppcheck - A tool for static C/C++ code analysis
00003  * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 
00020 #ifndef errorloggerH
00021 #define errorloggerH
00022 
00023 #include <list>
00024 #include <string>
00025 
00026 #include "config.h"
00027 #include "suppressions.h"
00028 
00029 class Token;
00030 class TokenList;
00031 
00032 /// @addtogroup Core
00033 /// @{
00034 
00035 /** @brief Simple container to be thrown when internal error is detected. */
00036 struct InternalError {
00037     InternalError(const Token *tok, const std::string &errorMsg);
00038     const Token *token;
00039     std::string errorMessage;
00040 };
00041 
00042 /** @brief enum class for severity. Used when reporting errors. */
00043 class CPPCHECKLIB Severity {
00044 public:
00045     /**
00046      * Message severities.
00047      */
00048     enum SeverityType {
00049         /**
00050          * No severity (default value).
00051          */
00052         none,
00053         /**
00054          * Programming error.
00055          * This indicates severe error like memory leak etc.
00056          * The error is certain.
00057          */
00058         error,
00059         /**
00060          * Warning.
00061          * Used for dangerous coding style that can cause severe runtime errors.
00062          * For example: forgetting to initialize a member variable in a constructor.
00063          */
00064         warning,
00065         /**
00066          * Style warning.
00067          * Used for general code cleanup recommendations. Fixing these
00068          * will not fix any bugs but will make the code easier to maintain.
00069          * For example: redundant code, unreachable code, etc.
00070          */
00071         style,
00072         /**
00073          * Performance warning.
00074          * Not an error as is but suboptimal code and fixing it probably leads
00075          * to faster performance of the compiled code.
00076          */
00077         performance,
00078         /**
00079          * Portability warning.
00080          * This warning indicates the code is not properly portable for
00081          * different platforms and bitnesses (32/64 bit). If the code is meant
00082          * to compile in different platforms and bitnesses these warnings
00083          * should be fixed.
00084          */
00085         portability,
00086         /**
00087          * Checking information.
00088          * Information message about the checking (process) itself. These
00089          * messages inform about header files not found etc issues that are
00090          * not errors in the code but something user needs to know.
00091          */
00092         information,
00093         /**
00094          * Debug message.
00095          * Debug-mode message useful for the developers.
00096          */
00097         debug
00098     };
00099 
00100     static std::string toString(SeverityType severity) {
00101         switch (severity) {
00102         case none:
00103             return "";
00104         case error:
00105             return "error";
00106         case warning:
00107             return "warning";
00108         case style:
00109             return "style";
00110         case performance:
00111             return "performance";
00112         case portability:
00113             return "portability";
00114         case information:
00115             return "information";
00116         case debug:
00117             return "debug";
00118         };
00119         throw InternalError(NULL, "Unknown severity");
00120     }
00121     static SeverityType fromString(const std::string &severity) {
00122         if (severity.empty())
00123             return none;
00124         if (severity == "none")
00125             return none;
00126         if (severity == "error")
00127             return error;
00128         if (severity == "warning")
00129             return warning;
00130         if (severity == "style")
00131             return style;
00132         if (severity == "performance")
00133             return performance;
00134         if (severity == "portability")
00135             return portability;
00136         if (severity == "information")
00137             return information;
00138         if (severity == "debug")
00139             return debug;
00140         return none;
00141     }
00142 };
00143 
00144 /**
00145  * @brief This is an interface, which the class responsible of error logging
00146  * should implement.
00147  */
00148 class CPPCHECKLIB ErrorLogger {
00149 public:
00150 
00151     /**
00152      * Wrapper for error messages, provided by reportErr()
00153      */
00154     class CPPCHECKLIB ErrorMessage {
00155     public:
00156         /**
00157          * File name and line number.
00158          * Internally paths are stored with / separator. When getting the filename
00159          * it is by default converted to native separators.
00160          */
00161         class CPPCHECKLIB FileLocation {
00162         public:
00163             FileLocation()
00164                 : line(0) {
00165             }
00166 
00167             FileLocation(const std::string &file, unsigned int aline)
00168                 : line(aline), _file(file) {
00169             }
00170 
00171             FileLocation(const Token* tok, const TokenList* list);
00172 
00173             /**
00174              * Return the filename.
00175              * @param convert If true convert path to native separators.
00176              * @return filename.
00177              */
00178             std::string getfile(bool convert = true) const;
00179 
00180             /**
00181              * Set the filename.
00182              * @param file Filename to set.
00183              */
00184             void setfile(const std::string &file);
00185 
00186             /**
00187              * Returns the location as a string. Format: [file:line]
00188              */
00189             std::string stringify() const;
00190 
00191             unsigned int line;
00192         private:
00193             std::string _file;
00194 
00195         };
00196 
00197         ErrorMessage(const std::list<FileLocation> &callStack, Severity::SeverityType severity, const std::string &msg, const std::string &id, bool inconclusive);
00198         ErrorMessage(const std::list<const Token*>& callstack, const TokenList* list, Severity::SeverityType severity, const std::string& id, const std::string& msg, bool inconclusive);
00199         ErrorMessage();
00200 
00201         /**
00202          * Format the error message in XML format
00203          * @param verbose use verbose message
00204          * @param ver XML version
00205          */
00206         std::string toXML(bool verbose, int ver) const;
00207 
00208         static std::string getXMLHeader(int xml_version);
00209         static std::string getXMLFooter(int xml_version);
00210 
00211         /**
00212          * Format the error message into a string.
00213          * @param verbose use verbose message
00214          * @param outputFormat Empty string to use default output format
00215          * or template to be used. E.g. "{file}:{line},{severity},{id},{message}"
00216          */
00217         std::string toString(bool verbose, const std::string &outputFormat = "") const;
00218 
00219         std::string serialize() const;
00220         bool deserialize(const std::string &data);
00221 
00222         std::list<FileLocation> _callStack;
00223         std::string _id;
00224 
00225         /** source file (not header) */
00226         std::string file0;
00227 
00228         Severity::SeverityType _severity;
00229         bool _inconclusive;
00230 
00231         /** set short and verbose messages */
00232         void setmsg(const std::string &msg);
00233 
00234         /** Short message (single line short message) */
00235         const std::string &shortMessage() const {
00236             return _shortMessage;
00237         }
00238 
00239         /** Verbose message (may be the same as the short message) */
00240         const std::string &verboseMessage() const {
00241             return _verboseMessage;
00242         }
00243 
00244     private:
00245         /**
00246          * Replace all occurrences of searchFor with replaceWith in the
00247          * given source.
00248          * @param source The string to modify
00249          * @param searchFor What should be searched for
00250          * @param replaceWith What will replace the found item
00251          */
00252         static void findAndReplace(std::string &source, const std::string &searchFor, const std::string &replaceWith);
00253 
00254         /** Short message */
00255         std::string _shortMessage;
00256 
00257         /** Verbose message */
00258         std::string _verboseMessage;
00259     };
00260 
00261     ErrorLogger() { }
00262     virtual ~ErrorLogger() { }
00263 
00264     /**
00265      * Information about progress is directed here.
00266      * Override this to receive the progress messages.
00267      *
00268      * @param outmsg Message to show e.g. "Checking main.cpp..."
00269      */
00270     virtual void reportOut(const std::string &outmsg) = 0;
00271 
00272     /**
00273      * Information about found errors and warnings is directed
00274      * here. Override this to receive the errormessages.
00275      *
00276      * @param msg Location and other information about the found error.
00277      */
00278     virtual void reportErr(const ErrorLogger::ErrorMessage &msg) = 0;
00279 
00280     /**
00281      * Report progress to client
00282      * @param filename main file that is checked
00283      * @param stage for example preprocess / tokenize / simplify / check
00284      * @param value progress value (0-100)
00285      */
00286     virtual void reportProgress(const std::string &filename, const char stage[], const std::size_t value) {
00287         (void)filename;
00288         (void)stage;
00289         (void)value;
00290     }
00291 
00292     /**
00293      * Output information messages.
00294      * @param msg Location and other information about the found error.
00295      */
00296     virtual void reportInfo(const ErrorLogger::ErrorMessage &msg) {
00297         reportErr(msg);
00298     }
00299 
00300     /**
00301      * Report list of unmatched suppressions
00302      * @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions)
00303      */
00304     void reportUnmatchedSuppressions(const std::list<Suppressions::SuppressionEntry> &unmatched);
00305 
00306     static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack);
00307 };
00308 
00309 /// @}
00310 
00311 #endif