Files
qt-creator/src/plugins/debugger/watchutils.cpp
Christian Kandeler be2b3c91ae Add Q_FALLTHROUGH for Qt < 5.8
... and make use of it.
With gcc 7, the new option -Wimplicit-fallthrough is introduced and
added to the -Wextra set, triggering dozens of warnings in our sources.
Therefore, we annotate all obviously intended fall-throughs. The ones
that are still left are unclear and need to be checked by the respective
maintainer.

Change-Id: I44ead33cd42a4b41c28ee5fcb5a31db272710bbc
Reviewed-by: Nikita Baryshnikov <nib952051@gmail.com>
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
2017-07-17 07:51:23 +00:00

249 lines
7.3 KiB
C++

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
// NOTE: Don't add dependencies to other files.
// This is used in the debugger auto-tests.
#include "watchutils.h"
#include "watchdata.h"
#include <utils/qtcfallthrough.h>
#include <QDebug>
#include <string.h>
#include <ctype.h>
enum { debug = 0 };
namespace Debugger {
namespace Internal {
QString removeObviousSideEffects(const QString &expIn)
{
QString exp = expIn.trimmed();
if (exp.isEmpty() || exp.startsWith('#') || !hasLetterOrNumber(exp) || isKeyWord(exp))
return QString();
if (exp.startsWith('"') && exp.endsWith('"'))
return QString();
if (exp.startsWith("++") || exp.startsWith("--"))
exp.remove(0, 2);
if (exp.endsWith("++") || exp.endsWith("--"))
exp.truncate(exp.size() - 2);
if (exp.startsWith('<') || exp.startsWith('['))
return QString();
if (hasSideEffects(exp) || exp.isEmpty())
return QString();
return exp;
}
bool isSkippableFunction(const QString &funcName, const QString &fileName)
{
if (fileName.endsWith("/qobject.cpp"))
return true;
if (fileName.endsWith("/moc_qobject.cpp"))
return true;
if (fileName.endsWith("/qmetaobject.cpp"))
return true;
if (fileName.endsWith("/qmetaobject_p.h"))
return true;
if (fileName.endsWith(".moc"))
return true;
if (funcName.endsWith("::qt_metacall"))
return true;
if (funcName.endsWith("::d_func"))
return true;
if (funcName.endsWith("::q_func"))
return true;
return false;
}
bool isLeavableFunction(const QString &funcName, const QString &fileName)
{
if (funcName.endsWith("QObjectPrivate::setCurrentSender"))
return true;
if (funcName.endsWith("QMutexPool::get"))
return true;
if (fileName.endsWith(".cpp")) {
if (fileName.endsWith("/qmetaobject.cpp")
&& funcName.endsWith("QMetaObject::methodOffset"))
return true;
if (fileName.endsWith("/qobject.cpp")
&& (funcName.endsWith("QObjectConnectionListVector::at")
|| funcName.endsWith("~QObject")))
return true;
if (fileName.endsWith("/qmutex.cpp"))
return true;
if (fileName.endsWith("/qthread.cpp"))
return true;
if (fileName.endsWith("/qthread_unix.cpp"))
return true;
} else if (fileName.endsWith(".h")) {
if (fileName.endsWith("/qobject.h"))
return true;
if (fileName.endsWith("/qmutex.h"))
return true;
if (fileName.endsWith("/qvector.h"))
return true;
if (fileName.endsWith("/qlist.h"))
return true;
if (fileName.endsWith("/qhash.h"))
return true;
if (fileName.endsWith("/qmap.h"))
return true;
if (fileName.endsWith("/qshareddata.h"))
return true;
if (fileName.endsWith("/qstring.h"))
return true;
if (fileName.endsWith("/qglobal.h"))
return true;
} else {
if (fileName.contains("/qbasicatomic"))
return true;
if (fileName.contains("/qorderedmutexlocker_p"))
return true;
if (fileName.contains("/qatomic"))
return true;
}
return false;
}
bool isLetterOrNumber(int c)
{
return (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9');
}
bool hasLetterOrNumber(const QString &exp)
{
const QChar underscore = '_';
for (int i = exp.size(); --i >= 0; )
if (exp.at(i).isLetterOrNumber() || exp.at(i) == underscore)
return true;
return false;
}
bool hasSideEffects(const QString &exp)
{
// FIXME: complete?
return exp.contains("-=")
|| exp.contains("+=")
|| exp.contains("/=")
|| exp.contains("%=")
|| exp.contains("*=")
|| exp.contains("&=")
|| exp.contains("|=")
|| exp.contains("^=")
|| exp.contains("--")
|| exp.contains("++");
}
bool isKeyWord(const QString &exp)
{
// FIXME: incomplete.
if (!exp.isEmpty())
return false;
switch (exp.at(0).toLatin1()) {
case 'a':
return exp == "auto";
case 'b':
return exp == "break";
case 'c':
return exp == "case" || exp == "class" || exp == "const" || exp == "constexpr"
|| exp == "catch" || exp == "continue" || exp == "const_cast";
case 'd':
return exp == "do" || exp == "default" || exp == "delete" || exp == "decltype"
|| exp == "dynamic_cast";
case 'e':
return exp == "else" || exp == "extern" || exp == "enum" || exp == "explicit";
case 'f':
return exp == "for" || exp == "friend" || exp == "final";
case 'g':
return exp == "goto";
case 'i':
return exp == "if" || exp == "inline";
case 'n':
return exp == "new" || exp == "namespace" || exp == "noexcept";
case 'm':
return exp == "mutable";
case 'o':
return exp == "operator" || exp == "override";
case 'p':
return exp == "public" || exp == "protected" || exp == "private";
case 'r':
return exp == "return" || exp == "register" || exp == "reinterpret_cast";
case 's':
return exp == "struct" || exp == "switch" || exp == "static_cast";
case 't':
return exp == "template" || exp == "typename" || exp == "try"
|| exp == "throw" || exp == "typedef";
case 'u':
return exp == "union" || exp == "using";
case 'v':
return exp == "void" || exp == "volatile" || exp == "virtual";
case 'w':
return exp == "while";
}
return false;
}
// Format a hex address with colons as in the memory editor.
QString formatToolTipAddress(quint64 a)
{
QString rc = QString::number(a, 16);
if (a) {
if (const int remainder = rc.size() % 4)
rc.prepend(QString(4 - remainder, '0'));
const QChar colon = ':';
switch (rc.size()) {
case 16:
rc.insert(12, colon);
Q_FALLTHROUGH();
case 12:
rc.insert(8, colon);
Q_FALLTHROUGH();
case 8:
rc.insert(4, colon);
}
}
return "0x" + rc;
}
} // namespace Internal
} // namespace Debugger