Commit fcc6b112 authored by Eike Ziller's avatar Eike Ziller
Browse files

Merge remote-tracking branch 'origin/3.4'

Conflicts:
	qtcreator.pri
	qtcreator.qbs

Change-Id: Iaff42d30008db13ecb685e5157c82292fe48b038
parents 57794c17 0501efdc
......@@ -30,6 +30,21 @@
from dumper import *
def stripTypeName(value):
type = value.type
try:
type = type.target()
except:
pass
return str(type.unqualified())
def extractPointerType(d, value):
postfix = ""
while stripTypeName(value) == "CPlusPlus::PointerType":
postfix += "*"
value = d.downcast(value["_elementType"]["_type"])
return readLiteral(d, value["_name"]) + postfix
def readTemplateName(d, value):
name = readLiteral(d, value["_identifier"]) + "<"
args = value["_templateArguments"]
......@@ -39,12 +54,7 @@ def readTemplateName(d, value):
for i in range(size):
if i > 0:
name += ", "
typeVal = d.downcast(start[i]["_type"])
postfix = ""
while str(typeVal.type.target().unqualified()) == "CPlusPlus::PointerType":
postfix += "*"
typeVal = d.downcast(typeVal["_elementType"]["_type"])
name += readLiteral(d, typeVal["_name"]) + postfix
name += extractPointerType(d, d.downcast(start[i]["_type"]))
name += ">"
return name
......@@ -121,11 +131,24 @@ def qdump__CPlusPlus__IntegerType(d, value):
d.putValue(value["_kind"])
d.putPlainChildren(value)
def qdump__CPlusPlus__FullySpecifiedType(d, value):
type = d.downcast(value["_type"])
typeName = stripTypeName(type)
if typeName == "CPlusPlus::NamedType":
dumpLiteral(d, type["_name"])
elif typeName == "CPlusPlus::PointerType":
d.putValue(d.hexencode(extractPointerType(d, type)), Hex2EncodedLatin1)
d.putPlainChildren(value)
def qdump__CPlusPlus__NamedType(d, value):
dumpLiteral(d, value["_name"])
d.putBetterType(value.type)
d.putPlainChildren(value)
def qdump__CPlusPlus__PointerType(d, value):
d.putValue(d.hexencode(extractPointerType(d, value)), Hex2EncodedLatin1)
d.putPlainChildren(value)
def qdump__CPlusPlus__TemplateNameId(d, value):
dumpLiteral(d, value)
d.putBetterType(value.type)
......
......@@ -948,16 +948,28 @@ class DumperBase:
else:
self.putValue(blob, Hex8EncodedLittleEndian)
if self.currentIName in self.expandedINames:
if self.isExpanded():
try:
# May fail on artificial items like xmm register data.
if not self.tryPutArrayContents(p, n, innerType):
#if not self.tryPutArrayContents(p, n, innerType):
with Children(self, childType=innerType, addrBase=p, addrStep=ts):
self.putFields(value)
except:
with Children(self, childType=innerType):
self.putFields(value)
if hasPlot and self.isSimpleType(innerType):
show = displayFormat == ArrayPlotFormat
iname = self.currentIName
data = []
if show:
base = self.createPointerValue(p, innerType)
data = [str(base[i]) for i in range(0, n)]
matplotSend(iname, show, data)
else:
#self.putValue(self.currentValue.value + " (not plottable)")
self.putField("plottable", "0")
def cleanAddress(self, addr):
if addr is None:
return "<no address>"
......@@ -1745,6 +1757,10 @@ class DumperBase:
self.qqEditable = {}
self.typeCache = {}
if hasPlot: # Hack for generic array type. [] is used as "type" name.
self.qqDumpers['[]'] = ""
self.qqFormats['[]'] = arrayForms()
for mod in self.dumpermodules:
m = importlib.import_module(mod)
dic = m.__dict__
......
......@@ -904,7 +904,7 @@ class Dumper(DumperBase):
self.report('token(\"%s\")' % args["token"])
def reportContinuation(self, args):
if "continuation" in args:
if not self.isShuttingDown_ and "continuation" in args:
self.report('continuation=\"%s\"' % args["continuation"])
def extractBlob(self, base, size):
......
......@@ -14,11 +14,7 @@ QT += core-private qml-private quick-private gui-private
QT += v8-private
}
!osx {
CONFIG += c++11
}
CONFIG += c++11
DEFINES -= QT_CREATOR
......
......@@ -78,6 +78,8 @@ enum KnownType
KT_QWindow = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 21,
KT_QWidget = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 22,
KT_QSharedPointer = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 23,
KT_QRegion = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 24,
KT_QWeakPointer = KT_Qt_Type + KT_HasSimpleDumper + KT_HasComplexDumper + 25,
// Types: Various QT movable types
KT_QPen = KT_Qt_Type + KT_Qt_MovableType + 30,
KT_QUrl = KT_Qt_Type + KT_Qt_MovableType + 31 + KT_HasSimpleDumper,
......@@ -144,6 +146,7 @@ enum KnownType
KT_QHostAddress = KT_Qt_Type + KT_HasSimpleDumper + 92,
KT_QProcess = KT_Qt_Type + KT_HasSimpleDumper + 93,
KT_QTimeZone = KT_Qt_Type + KT_HasSimpleDumper + 94,
KT_QIPv6Address = KT_Qt_Type + KT_HasSimpleDumper + 95,
// Types: Qt primitive types
KT_QFixed = KT_Qt_Type + KT_Qt_PrimitiveType + 90,
KT_QTextItem = KT_Qt_Type + KT_Qt_PrimitiveType + 91,
......
......@@ -366,20 +366,6 @@ enum PointerFormats
FormatUcs4String = 105
};
enum DumpEncoding // WatchData encoding of GDBMI values
{
DumpEncodingAscii = 0,
DumpEncodingBase64_Utf16_WithQuotes = 2,
DumpEncodingHex_Ucs4_LittleEndian_WithQuotes = 3,
DumpEncodingBase64_Utf16 = 4,
DumpEncodingHex_Latin1_WithQuotes = 6,
DumpEncodingHex_Utf8_LittleEndian_WithQuotes = 9,
DumpEncodingJulianDate = 14,
DumpEncodingMillisecondsSinceMidnight = 15,
DumpEncodingJulianDateAndMillisecondsSinceMidnight = 16,
DumpEncodingMillisecondsSinceEpoch = 29
};
/* Recode arrays/pointers of char*, wchar_t according to users
* specification. Handles char formats for 'char *', '0x834478 "hallo.."'
* and 'wchar_t *', '0x834478 "hallo.."', 'wchar_t[56] "hallo"', etc.
......@@ -622,6 +608,7 @@ SymbolGroupNode::SymbolGroupNode(SymbolGroup *symbolGroup,
, m_symbolGroup(symbolGroup)
, m_module(module)
, m_index(index)
, m_dumperValueEncoding(0)
, m_dumperType(-1)
, m_dumperContainerSize(-1)
, m_dumperSpecialInfo(0)
......@@ -1059,7 +1046,7 @@ bool SymbolGroupNode::runSimpleDumpers(const SymbolGroupValueContext &ctx)
return true;
if (testFlags(SimpleDumperMask))
return false;
addFlags(dumpSimpleType(this , ctx, &m_dumperValue,
addFlags(dumpSimpleType(this , ctx, &m_dumperValue, &m_dumperValueEncoding,
&m_dumperType, &m_dumperContainerSize,
&m_dumperSpecialInfo, &m_memory));
if (symbolGroupDebug)
......@@ -1069,12 +1056,14 @@ bool SymbolGroupNode::runSimpleDumpers(const SymbolGroupValueContext &ctx)
return testFlags(SimpleDumperOk);
}
std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx)
std::wstring SymbolGroupNode::simpleDumpValue(const SymbolGroupValueContext &ctx, int *encoding)
{
if (testFlags(Uninitialized))
return L"<not in scope>";
if (runSimpleDumpers(ctx))
if (runSimpleDumpers(ctx)) {
*encoding = m_dumperValueEncoding;
return m_dumperValue;
}
return symbolGroupFixedValue();
}
......@@ -1122,7 +1111,8 @@ int SymbolGroupNode::dumpNode(std::ostream &str,
const std::string watchExp = t.empty() ? aName : watchExpression(addr, t, m_dumperType, m_module);
SymbolGroupNode::dumpBasicData(str, aName, aFullIName, t, watchExp);
std::wstring value = simpleDumpValue(ctx);
int encoding = 0;
std::wstring value = simpleDumpValue(ctx, &encoding);
if (addr) {
str << std::hex << std::showbase << ",addr=\"" << addr << '"';
......@@ -1145,28 +1135,6 @@ int SymbolGroupNode::dumpNode(std::ostream &str,
bool valueEditable = !uninitialized;
bool valueEnabled = !uninitialized;
// Shall it be recoded?
int encoding = 0;
switch (knownType(t, 0)) {
case KT_QDate:
encoding = DumpEncodingJulianDate;
break;
case KT_QTime:
encoding = DumpEncodingMillisecondsSinceMidnight;
break;
case KT_QDateTime:
if (!value.compare(L"(invalid)"))
break;
encoding = QtInfo::get(ctx).version < 5
? DumpEncodingJulianDateAndMillisecondsSinceMidnight
: DumpEncodingMillisecondsSinceEpoch;
break;
case KT_QTimeZone: // Based on a QByteArray dumper
case KT_QByteArray:
if (QtInfo::get(ctx).version > 4)
encoding = DumpEncodingHex_Latin1_WithQuotes;
break;
}
if (encoding) {
str << ",valueencoded=\"" << encoding << "\",value=\"" << gdbmiWStringFormat(value) <<'"';
} else if (dumpParameters.recode(t, aFullIName, ctx, addr, &value, &encoding)) {
......
......@@ -48,6 +48,21 @@ struct SymbolGroupValueContext;
class SymbolGroupNode;
class MemoryHandle;
enum DumpEncoding // WatchData encoding of GDBMI values
{
DumpEncodingAscii = 0,
DumpEncodingBase64_Utf16_WithQuotes = 2,
DumpEncodingHex_Ucs4_LittleEndian_WithQuotes = 3,
DumpEncodingBase64_Utf16 = 4,
DumpEncodingHex_Latin1_WithQuotes = 6,
DumpEncodingHex_Utf8_LittleEndian_WithQuotes = 9,
DumpEncodingJulianDate = 14,
DumpEncodingMillisecondsSinceMidnight = 15,
DumpEncodingJulianDateAndMillisecondsSinceMidnight = 16,
DumpEncodingIPv6AddressAndHexScopeId = 27,
DumpEncodingMillisecondsSinceEpoch = 29
};
// Helper struct used for check results when recoding CDB char pointer output.
struct DumpParameterRecodeResult
{
......@@ -249,6 +264,7 @@ public:
std::wstring symbolGroupFixedValue() const;
bool assign(const std::string &value, std::string *errorMessage = 0);
std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx, int *encoding);
// A quick check if symbol is valid by checking for inaccessible value
bool isMemoryAccessible() const;
......@@ -291,7 +307,6 @@ private:
// Notify about expansion/collapsing of a node, shift indexes
bool notifyIndexesMoved(ULONG index, bool inserted, ULONG offset);
bool runSimpleDumpers(const SymbolGroupValueContext &ctx);
std::wstring simpleDumpValue(const SymbolGroupValueContext &ctx);
ULONG nextSymbolIndex() const;
SymbolGroup *const m_symbolGroup;
......@@ -299,6 +314,7 @@ private:
ULONG m_index;
DEBUG_SYMBOL_PARAMETERS m_parameters; // Careful when using ParentSymbol. It might not be correct.
std::wstring m_dumperValue;
int m_dumperValueEncoding;
int m_dumperType;
int m_dumperContainerSize;
void *m_dumperSpecialInfo; // Opaque information passed from simple to complex dumpers
......
......@@ -255,6 +255,7 @@ void formatKnownTypeFlags(std::ostream &os, KnownType kt);
// complex dumpers
unsigned dumpSimpleType(SymbolGroupNode *n, const SymbolGroupValueContext &ctx,
std::wstring *s,
int *encoding = 0,
int *knownType = 0,
int *containerSizeIn = 0,
void **specialInfoIn = 0,
......
......@@ -141,6 +141,27 @@ QString BuildableHelperLibrary::qtVersionForQMake(const QString &qmakePath)
return QString();
}
QString BuildableHelperLibrary::filterForQmakeFileDialog()
{
QString filter = QLatin1String("qmake (");
const QStringList commands = possibleQMakeCommands();
for (int i = 0; i < commands.size(); ++i) {
if (i)
filter += QLatin1Char(' ');
if (HostOsInfo::isMacHost())
// work around QTBUG-7739 that prohibits filters that don't start with *
filter += QLatin1Char('*');
filter += commands.at(i);
if (HostOsInfo::isAnyUnixHost() && !HostOsInfo::isMacHost())
// kde bug, we need at least one wildcard character
// see QTCREATORBUG-7771
filter += QLatin1Char('*');
}
filter += QLatin1Char(')');
return filter;
}
QStringList BuildableHelperLibrary::possibleQMakeCommands()
{
// On Windows it is always "qmake.exe"
......
......@@ -50,6 +50,7 @@ public:
static QString qtVersionForQMake(const QString &qmakePath);
// returns something like qmake4, qmake, qmake-qt4 or whatever distributions have chosen (used by QtVersion)
static QStringList possibleQMakeCommands();
static QString filterForQmakeFileDialog();
static QString byInstallDataHelper(const QString &sourcePath,
const QStringList &sourceFileNames,
......
......@@ -101,6 +101,7 @@ RunControl *AndroidDebugSupport::createDebugRunControl(AndroidRunConfiguration *
if (ToolChain *tc = ToolChainKitInformation::toolChain(kit))
params.toolChainAbi = tc->targetAbi();
params.executable = target->activeBuildConfiguration()->buildDirectory().toString() + QLatin1String("/app_process");
params.skipExecutableValidation = true;
params.remoteChannel = runConfig->remoteChannel();
params.solibSearchPath = AndroidManager::androidQtSupport(target)->soLibSearchPath(target);
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
......
......@@ -419,10 +419,19 @@ void AndroidDeployQtStep::run(QFutureInterface<bool> &fi)
}
emit addOutput(tr("Pulling files necessary for debugging."), MessageOutput);
QString localAppProcessFile = QString::fromLatin1("%1/app_process").arg(m_buildDirectory);
runCommand(m_adbPath,
AndroidDeviceInfo::adbSelector(m_serialNumber)
<< QLatin1String("pull") << QLatin1String("/system/bin/app_process")
<< QString::fromLatin1("%1/app_process").arg(m_buildDirectory));
<< localAppProcessFile);
// Workaround for QTCREATORBUG-14201: /system/bin/app_process might be a link to asan/app_process
if (!QFileInfo::exists(localAppProcessFile)) {
runCommand(m_adbPath,
AndroidDeviceInfo::adbSelector(m_serialNumber)
<< QLatin1String("pull") << QLatin1String("/system/bin/asan/app_process")
<< localAppProcessFile);
}
runCommand(m_adbPath,
AndroidDeviceInfo::adbSelector(m_serialNumber) << QLatin1String("pull")
<< QLatin1String("/system/lib/libc.so")
......
......@@ -1061,7 +1061,8 @@ int ClangCompletionAssistProcessor::startCompletionInternal(const QString fileNa
foreach (ClangAssistProposalItem *item, items.values())
m_completions.append(item);
addSnippets();
if (m_model->m_completionOperator == T_EOF_SYMBOL)
addSnippets();
return m_startPosition;
}
......
......@@ -314,6 +314,7 @@ void CppToolsPlugin::test_completion()
actualCompletions.sort();
expectedCompletions.sort();
QEXPECT_FAIL("template_as_base: explicit typedef from base", "QTCREATORBUG-14218", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort);
......@@ -321,6 +322,8 @@ void CppToolsPlugin::test_completion()
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort);
QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort);
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort);
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
QCOMPARE(actualCompletions, expectedCompletions);
}
......@@ -708,6 +711,34 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Other")
<< QLatin1String("otherMember"));
QTest::newRow("template_as_base: typedef not available in derived") << _(
"class Data { int dataMember; };\n"
"template <class T> struct Base { typedef T F; };\n"
"template <class T> struct Derived : Base<T> { F f; };\n"
"\n"
"void func() {\n"
" Derived<Data> d;\n"
" @\n"
"}\n"
) << _("d.f.") << QStringList();
QTest::newRow("template_as_base: explicit typedef from base") << _(
"class Data { int dataMember; };\n"
"template <class T> struct Base { typedef T F; };\n"
"template <class T> struct Derived : Base<T>\n"
"{\n"
" typedef typename Base<T>::F F;\n"
" F f;\n"
"};\n"
"\n"
"void func() {\n"
" Derived<Data> d;\n"
" @\n"
"}\n"
) << _("d.f.") << (QStringList()
<< QLatin1String("Data")
<< QLatin1String("dataMember"));
QTest::newRow("use_global_identifier_as_base_class: derived as global and base as global") << _(
"struct Global\n"
"{\n"
......@@ -2714,6 +2745,76 @@ void CppToolsPlugin::test_completion_data()
) << _("t.p->") << (QStringList()
<< QLatin1String("Foo")
<< QLatin1String("bar"));
QTest::newRow("pointer_indirect_specialization_double_indirection") << _(
"template<typename _Tp>\n"
"struct Traits { };\n"
"\n"
"template<typename _Tp>\n"
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
"\n"
"struct Foo { int bar; };\n"
"\n"
"template<typename _Tp>\n"
"struct IndirectT\n"
"{\n"
" typedef Traits<_Tp> TraitsT;\n"
" typedef typename TraitsT::pointer pointer;\n"
" pointer p;\n"
"};\n"
"\n"
"template<typename _Tp>\n"
"struct Temp\n"
"{\n"
" typedef _Tp *pointer;\n"
" typedef IndirectT<pointer> indirect;\n"
"};\n"
"\n"
"void func()\n"
"{\n"
" Temp<Foo>::indirect t;\n"
" @\n"
"}\n"
) << _("t.p->") << (QStringList()
<< QLatin1String("Foo")
<< QLatin1String("bar"));
QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _(
"template<typename _Tp>\n"
"struct Traits { };\n"
"\n"
"template<typename _Tp>\n"
"struct Traits<_Tp*> { typedef _Tp *pointer; };\n"
"\n"
"struct Foo { int bar; };\n"
"\n"
"template<typename _Tp>\n"
"struct IndirectT\n"
"{\n"
" typedef Traits<_Tp> TraitsT;\n"
" typedef typename TraitsT::pointer pointer;\n"
" pointer p;\n"
"};\n"
"\n"
"template<typename _Tp>\n"
"struct TempBase { typedef _Tp *pointer; };\n"
"\n"
"template<typename _Tp>\n"
"struct Temp : public TempBase<_Tp>\n"
"{\n"
" typedef TempBase<_Tp> _Base;\n"
" typedef typename _Base::pointer pointer;\n"
" typedef IndirectT<pointer> indirect;\n"
"};\n"
"\n"
"void func()\n"
"{\n"
" Temp<Foo>::indirect t;\n"
" @\n"
"}\n"
) << _("t.p->") << (QStringList()
<< QLatin1String("Foo")
<< QLatin1String("bar"));
}
void CppToolsPlugin::test_completion_member_access_operator()
......
......@@ -1793,6 +1793,8 @@ void DebuggerEngine::setStateDebugging(bool on)
void DebuggerEngine::validateExecutable(DebuggerStartParameters *sp)
{
if (sp->skipExecutableValidation)
return;
if (sp->languages == QmlLanguage)
return;
QString binary = sp->executable;
......
......@@ -90,6 +90,7 @@ public:
startMode(NoStartMode),
closeMode(KillAtClose),
useCtrlCStub(false),
skipExecutableValidation(false),
testCase(0)
{}
......@@ -157,6 +158,9 @@ public:
QString remoteExecutable;
bool useCtrlCStub;
// Used by Android to avoid false positives on warnOnRelease
bool skipExecutableValidation;
// For Debugger testing.
int testCase;
};
......
......@@ -252,14 +252,29 @@ void Register::guessMissingData()
fixup(this, IntegerRegister, 0);
}
static QString subTypeName(RegisterKind kind, int size)
static QString subTypeName(RegisterKind kind, int size, RegisterFormat format)
{
if (kind == IntegerRegister)
return QString::fromLatin1("[i%1]").arg(size * 8);
if (kind == FloatRegister)
return QString::fromLatin1("[f%1]").arg(size * 8);
QTC_ASSERT(false, /**/);
return QString();
QString name(QLatin1Char('['));
switch (kind) {
case IntegerRegister: name += QLatin1Char('i'); break;
case FloatRegister: name += QLatin1Char('f'); break;
default: break;
}
name += QString::number(size);
switch (format) {
case BinaryFormat: name += QLatin1Char('b'); break;
case OctalFormat: name += QLatin1Char('o'); break;
case DecimalFormat: name += QLatin1Char('d'); break;
case HexadecimalFormat: name += QLatin1Char('x'); break;
case CharacterFormat: name += QLatin1Char('c'); break;
}
name += QLatin1Char(']');
return name;
}
static uint decodeHexChar(unsigned char c)
......@@ -305,15 +320,29 @@ bool RegisterValue::operator==(const RegisterValue &other)
return v.u64[0] == other.v.u64[0] && v.u64[1] == other.v.u64[1];
}
static QByteArray format(quint64 v, int base, int size)
static QByteArray formatRegister(quint64 v, int size, RegisterFormat format)
{
QByteArray result = QByteArray::number(v, base);
if (base == 16)
QByteArray result;
if (format == HexadecimalFormat) {
result = QByteArray::number(v, 16);
result.prepend(QByteArray(2*size - result.size(), '0'));
} else if (format == DecimalFormat) {
result = QByteArray::number(v, 10);
result.prepend(QByteArray(2*size - result.size(), ' '));
} else if (format == CharacterFormat) {
if (v >= 32 && v < 127) {
result += '\'';
result += char(v);
result += '\'';
} else {
result += " ";
}
result.prepend(QByteArray(2*size - result.size(), ' '));