Split the qt_message_output function in two
authorThiago Macieira <thiago.macieira@intel.com>
Sun, 22 Apr 2012 19:35:10 +0000 (21:35 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 19 Sep 2012 17:54:44 +0000 (19:54 +0200)
This way, I can ensure that the noreturn qFatal function calls a
noreturn function as its last action.

Change-Id: I6db7aa2539af430414645f386d7fce87cdb97186
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
src/corelib/global/qlogging.cpp

index 38c2522..77d3baa 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
+#if !defined(Q_CC_MSVC)
+Q_NORETURN
+#endif
+static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message);
+static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message);
+
+static bool isFatal(QtMsgType msgType)
+{
+    if (msgType == QtFatalMsg)
+        return true;
+
+    if (msgType == QtWarningMsg) {
+        static bool fatalWarnings = qEnvironmentVariableIsSet("QT_FATAL_WARNINGS");
+        return fatalWarnings;
+    }
+
+    return false;
+}
+
 /*!
     \class QMessageLogContext
     \inmodule QtCore
@@ -175,7 +194,7 @@ static void qEmergencyOut(QtMsgType msgType, const char *msg, va_list ap) Q_DECL
     \internal
 */
 static void qt_message(QtMsgType msgType, const QMessageLogContext &context, const char *msg,
-                       va_list ap)
+                       va_list ap, QString &buf)
 {
 #if !defined(QT_NO_EXCEPTIONS)
     if (std::uncaught_exception()) {
@@ -183,7 +202,6 @@ static void qt_message(QtMsgType msgType, const QMessageLogContext &context, con
         return;
     }
 #endif
-    QString buf;
     if (msg) {
         QT_TRY {
             buf = QString().vsprintf(msg, ap);
@@ -195,7 +213,7 @@ static void qt_message(QtMsgType msgType, const QMessageLogContext &context, con
 #endif
         }
     }
-    qt_message_output(msgType, context, buf);
+    qt_message_print(msgType, context, buf);
 }
 
 #undef qDebug
@@ -207,10 +225,15 @@ static void qt_message(QtMsgType msgType, const QMessageLogContext &context, con
 */
 void QMessageLogger::debug(const char *msg, ...) const
 {
+    QString message;
+
     va_list ap;
     va_start(ap, msg); // use variable arg list
-    qt_message(QtDebugMsg, context, msg, ap);
+    qt_message(QtDebugMsg, context, msg, ap, message);
     va_end(ap);
+
+    if (isFatal(QtDebugMsg))
+        qt_message_fatal(QtDebugMsg, context, message);
 }
 
 #ifndef QT_NO_DEBUG_STREAM
@@ -251,10 +274,15 @@ QNoDebug QMessageLogger::noDebug() const Q_DECL_NOTHROW
 */
 void QMessageLogger::warning(const char *msg, ...) const
 {
+    QString message;
+
     va_list ap;
     va_start(ap, msg); // use variable arg list
-    qt_message(QtWarningMsg, context, msg, ap);
+    qt_message(QtWarningMsg, context, msg, ap, message);
     va_end(ap);
+
+    if (isFatal(QtWarningMsg))
+        qt_message_fatal(QtWarningMsg, context, message);
 }
 
 #ifndef QT_NO_DEBUG_STREAM
@@ -282,10 +310,15 @@ QDebug QMessageLogger::warning() const
 */
 void QMessageLogger::critical(const char *msg, ...) const
 {
+    QString message;
+
     va_list ap;
     va_start(ap, msg); // use variable arg list
-    qt_message(QtCriticalMsg, context, msg, ap);
+    qt_message(QtCriticalMsg, context, msg, ap, message);
     va_end(ap);
+
+    if (isFatal(QtCriticalMsg))
+        qt_message_fatal(QtCriticalMsg, context, message);
 }
 
 #ifndef QT_NO_DEBUG_STREAM
@@ -312,13 +345,14 @@ QDebug QMessageLogger::critical() const
 */
 void QMessageLogger::fatal(const char *msg, ...) const Q_DECL_NOTHROW
 {
+    QString message;
+
     va_list ap;
     va_start(ap, msg); // use variable arg list
-    QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, context, msg, ap));
-#ifndef Q_CC_MSVC
-    Q_UNREACHABLE();
-#endif
+    QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, context, msg, ap, message));
     va_end(ap);
+
+    qt_message_fatal(QtFatalMsg, context, message);
 }
 
 /*!
@@ -726,10 +760,7 @@ static void qDefaultMsgHandler(QtMsgType type, const char *buf)
     qDefaultMessageHandler(type, emptyContext, QLatin1String(buf));
 }
 
-/*!
-    \internal
-*/
-void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
+static void qt_message_print(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
 {
     if (!msgHandler)
         msgHandler = qDefaultMsgHandler;
@@ -743,11 +774,10 @@ void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, con
     } else {
         (*msgHandler)(msgType, message.toLocal8Bit().constData());
     }
+}
 
-    if (msgType == QtFatalMsg
-            || (msgType == QtWarningMsg
-                && qEnvironmentVariableIsSet("QT_FATAL_WARNINGS")) ) {
-
+static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message)
+{
 #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
         wchar_t contextFileL[256];
         // we probably should let the compiler do this for us, by
@@ -755,26 +785,39 @@ void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, con
         // the first place, but the #ifdefery above is very complex
         // and we wouldn't be able to change it later on...
         convert_to_wchar_t_elided(contextFileL, sizeof contextFileL / sizeof *contextFileL, context.file);
-        // get the current report mode
-        int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
-        _CrtSetReportMode(_CRT_ERROR, reportMode);
+    // get the current report mode
+    int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
+    _CrtSetReportMode(_CRT_ERROR, reportMode);
 
         int ret = _CrtDbgReportW(_CRT_ERROR, contextFileL,
-                                 context.line, _CRT_WIDE(QT_VERSION_STR),
-                                 reinterpret_cast<const wchar_t *> (
-                                     message.utf16()));
-        if (ret == 0  && reportMode & _CRTDBG_MODE_WNDW)
-            return; // ignore
-        else if (ret == 1)
-            _CrtDbgBreak();
+                             context.line, _CRT_WIDE(QT_VERSION_STR),
+                             reinterpret_cast<const wchar_t *> (
+                                 message.utf16()));
+    if (ret == 0  && reportMode & _CRTDBG_MODE_WNDW)
+        return; // ignore
+    else if (ret == 1)
+        _CrtDbgBreak();
+#else
+    Q_UNUSED(context);
+    Q_UNUSED(message);
 #endif
 
 #if (defined(Q_OS_UNIX) || defined(Q_CC_MINGW))
-        abort(); // trap; generates core dump
+    abort(); // trap; generates core dump
 #else
-        exit(1); // goodbye cruel world
+    exit(1); // goodbye cruel world
 #endif
-    }
+}
+
+
+/*!
+    \internal
+*/
+void qt_message_output(QtMsgType msgType, const QMessageLogContext &context, const QString &message)
+{
+    qt_message_print(msgType, context, message);
+    if (isFatal(msgType))
+        qt_message_fatal(msgType, context, message);
 }
 
 void qErrnoWarning(const char *msg, ...)