forked from qt-creator/qt-creator
Merge remote branch 'origin/1.3'
Conflicts: src/plugins/cpptools/cppcodecompletion.cpp src/plugins/debugger/gdb/remotegdbadapter.cpp
This commit is contained in:
@@ -2929,7 +2929,7 @@ static void qDumpQVector(QDumper &d)
|
||||
|
||||
d.putItemCount("value", n);
|
||||
d.putItem("valueeditable", "false");
|
||||
d.putItem("numchild", n);
|
||||
d.putItem("numchild", nn);
|
||||
if (d.dumpChildren) {
|
||||
QByteArray strippedInnerType = stripPointerType(d.innerType);
|
||||
const char *stripped = innerIsPointerType ? strippedInnerType.data() : 0;
|
||||
@@ -2998,10 +2998,26 @@ static void qDumpQWeakPointer(QDumper &d)
|
||||
#endif // QT_VERSION >= 0x040500
|
||||
#endif // QT_BOOTSTRAPPED
|
||||
|
||||
#ifdef Q_CC_MSVC
|
||||
// A friendly list that grants access to its head.
|
||||
template <class T> class FriendlyList : public std::list<T> {
|
||||
public:
|
||||
typedef _Node Node;
|
||||
static const Node *head(const std::list<T> *list) {
|
||||
return static_cast<const FriendlyList *>(list)->_Myhead;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static void qDumpStdList(QDumper &d)
|
||||
{
|
||||
const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data);
|
||||
#ifdef Q_CC_MSVC
|
||||
/* Extensive checks to avoid _HAS_ITERATOR_DEBUGGING asserts at all cost.
|
||||
* Examine the head element which is present in empty lists as well.
|
||||
* It could be even further checked if the type was known. */
|
||||
const void *head = FriendlyList<int>::head(&list);
|
||||
qCheckAccess(head);
|
||||
const int size = static_cast<int>(list.size());
|
||||
if (size < 0)
|
||||
return;
|
||||
@@ -3052,6 +3068,43 @@ static void qDumpStdList(QDumper &d)
|
||||
d.disarm();
|
||||
}
|
||||
|
||||
#ifdef Q_CC_MSVC
|
||||
// A friendly red-black tree that is able to access the node type and head
|
||||
// pointer. The class _Tree is used for the std::map/std::set implementations in
|
||||
// MS VS CC. It has a head element pointer (with left and right) that exists
|
||||
// even if it is empty. Provides a check() function to perform extensive checks
|
||||
// to avoid _HAS_ITERATOR_DEBUGGING asserts at all cost.
|
||||
template <class RedBlackTreeTraits> class FriendlyRedBlackTree : public std::_Tree<RedBlackTreeTraits> {
|
||||
public:
|
||||
static inline void check(const std::_Tree<RedBlackTreeTraits> *fs, bool *ok);
|
||||
};
|
||||
|
||||
template <class RedBlackTreeTraits>
|
||||
void FriendlyRedBlackTree<RedBlackTreeTraits>::check(const std::_Tree<RedBlackTreeTraits> *fs, bool *ok)
|
||||
{
|
||||
*ok = false;
|
||||
const FriendlyRedBlackTree *friendlyTree = static_cast<const FriendlyRedBlackTree*>(fs);
|
||||
// Check the red/black tree
|
||||
const _Node *head = friendlyTree->_Myhead;
|
||||
qCheckAccess(head);
|
||||
if (head->_Color != _Red && head->_Color != _Black)
|
||||
return;
|
||||
const _Node *left = head->_Left;
|
||||
if (left && left != head) {
|
||||
qCheckAccess(left);
|
||||
if (left->_Color != _Red && left->_Color != _Black)
|
||||
return;
|
||||
}
|
||||
const _Node *right= head->_Right;
|
||||
if (right && right != left) {
|
||||
qCheckAccess(right);
|
||||
if (right->_Color != _Red && right->_Color != _Black)
|
||||
return;
|
||||
}
|
||||
*ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Dump out an arbitrary map. To iterate the map,
|
||||
* it is cast to a map of <KeyType,Value>. 'int' can be used for both
|
||||
* for all types if the implementation does not depend on the types
|
||||
@@ -3072,6 +3125,16 @@ static void qDumpStdMapHelper(QDumper &d)
|
||||
const int nn = map.size();
|
||||
if (nn < 0)
|
||||
return;
|
||||
#ifdef Q_CC_MSVC
|
||||
// Additional checks to avoid _HAS_ITERATOR_DEBUGGING asserts
|
||||
typedef std::pair<const KeyType, ValueType> RedBlackTreeEntryType;
|
||||
typedef std::_Tmap_traits<KeyType, ValueType, std::less<KeyType>, std::allocator<RedBlackTreeEntryType>, false>
|
||||
MapRedBlackTreeTraits;
|
||||
bool ok;
|
||||
FriendlyRedBlackTree<MapRedBlackTreeTraits>::check(&map, &ok);
|
||||
if (!ok)
|
||||
return;
|
||||
#endif
|
||||
Q_TYPENAME DummyType::const_iterator it = map.begin();
|
||||
const Q_TYPENAME DummyType::const_iterator cend = map.end();
|
||||
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
|
||||
@@ -3178,6 +3241,15 @@ static void qDumpStdSetHelper(QDumper &d)
|
||||
const int nn = set.size();
|
||||
if (nn < 0)
|
||||
return;
|
||||
#ifdef Q_CC_MSVC
|
||||
// Additional checks to avoid _HAS_ITERATOR_DEBUGGING asserts
|
||||
typedef std::_Tset_traits<KeyType, std::less<KeyType> , std::allocator<KeyType>, false>
|
||||
SetRedBlackTreeTraits;
|
||||
bool ok;
|
||||
FriendlyRedBlackTree<SetRedBlackTreeTraits>::check(&set, &ok);
|
||||
if (!ok)
|
||||
return;
|
||||
#endif
|
||||
Q_TYPENAME DummyType::const_iterator it = set.begin();
|
||||
const Q_TYPENAME DummyType::const_iterator cend = set.end();
|
||||
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
|
||||
|
@@ -48,13 +48,32 @@
|
||||
|
||||
// Test uninitialized variables allocing memory
|
||||
bool optTestUninitialized = false;
|
||||
bool optTestAll = false;
|
||||
bool optEmptyContainers = false;
|
||||
unsigned optVerbose = 0;
|
||||
|
||||
// Provide address of type of be tested.
|
||||
// When testing unitialized memory, allocate at random.
|
||||
template <class T>
|
||||
inline T* testAddress(T* in)
|
||||
{
|
||||
return optTestUninitialized ?
|
||||
(reinterpret_cast<T*>(new char[sizeof(T)]))
|
||||
: in;
|
||||
unsigned char *mem = 0;
|
||||
if (optTestUninitialized) {
|
||||
mem = new unsigned char[sizeof(T)];
|
||||
for (unsigned int i = 0; i < sizeof(T); i++) {
|
||||
mem[i] = char(rand() % 255u);
|
||||
}
|
||||
} else {
|
||||
mem = reinterpret_cast<unsigned char*>(in);
|
||||
}
|
||||
if (optVerbose) {
|
||||
for (unsigned int i = 0; i < sizeof(T); i++) {
|
||||
unsigned int b = mem[i];
|
||||
printf("%2d %2x %3d\n", i, b, b);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
return reinterpret_cast<T*>(mem);
|
||||
}
|
||||
|
||||
/* Test program for Dumper development/porting.
|
||||
@@ -175,8 +194,10 @@ static int dumpQMapIntInt()
|
||||
QMap<int,int> test;
|
||||
QMapNode<int,int> mapNode;
|
||||
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
|
||||
test.insert(42, 43);
|
||||
test.insert(43, 44);
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(42, 43);
|
||||
test.insert(43, 44);
|
||||
}
|
||||
prepareInBuffer("QMap", "local.qmapintint", "local.qmapintint", "int@int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(int), sizeof(mapNode), valueOffset);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -189,8 +210,10 @@ static int dumpQMapIntString()
|
||||
QMap<int,QString> test;
|
||||
QMapNode<int,QString> mapNode;
|
||||
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
|
||||
test.insert(42, QLatin1String("fortytwo"));
|
||||
test.insert(43, QLatin1String("fortytree"));
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(42, QLatin1String("fortytwo"));
|
||||
test.insert(43, QLatin1String("fortytree"));
|
||||
}
|
||||
prepareInBuffer("QMap", "local.qmapintqstring", "local.qmapintqstring", "int@QString");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(QString), sizeof(mapNode), valueOffset);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -201,8 +224,10 @@ static int dumpQMapIntString()
|
||||
static int dumpQSetInt()
|
||||
{
|
||||
QSet<int> test;
|
||||
test.insert(42);
|
||||
test.insert(43);
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(42);
|
||||
test.insert(43);
|
||||
}
|
||||
prepareInBuffer("QSet", "local.qsetint", "local.qsetint", "int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -216,9 +241,11 @@ static int dumpQMapQStringString()
|
||||
QMap<QString,QString> test;
|
||||
QMapNode<QString,QString> mapNode;
|
||||
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
|
||||
test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
|
||||
test.insert(QLatin1String("423"), QLatin1String("fortytree"));
|
||||
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString");
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
|
||||
test.insert(QLatin1String("423"), QLatin1String("fortytree"));
|
||||
}
|
||||
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(QString), sizeof(mapNode), valueOffset);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
@@ -278,8 +305,10 @@ static int dumpStdWString()
|
||||
static int dumpStdStringList()
|
||||
{
|
||||
std::list<std::string> test;
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
if (!optEmptyContainers) {
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
}
|
||||
prepareInBuffer("std::list", "local.stringlist", "local.stringlist", "std::string");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<std::string>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -290,8 +319,10 @@ static int dumpStdStringList()
|
||||
static int dumpStdStringQList()
|
||||
{
|
||||
QList<std::string> test;
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
if (!optEmptyContainers) {
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
}
|
||||
prepareInBuffer("QList", "local.stringqlist", "local.stringqlist", "std::string");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -302,8 +333,10 @@ static int dumpStdStringQList()
|
||||
static int dumpStdIntList()
|
||||
{
|
||||
std::list<int> test;
|
||||
test.push_back(1);
|
||||
test.push_back(2);
|
||||
if (!optEmptyContainers) {
|
||||
test.push_back(1);
|
||||
test.push_back(2);
|
||||
}
|
||||
prepareInBuffer("std::list", "local.intlist", "local.intlist", "int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -314,8 +347,10 @@ static int dumpStdIntList()
|
||||
static int dumpStdIntVector()
|
||||
{
|
||||
std::vector<int> test;
|
||||
test.push_back(1);
|
||||
test.push_back(2);
|
||||
if (!optEmptyContainers) {
|
||||
test.push_back(1);
|
||||
test.push_back(2);
|
||||
}
|
||||
prepareInBuffer("std::vector", "local.intvector", "local.intvector", "int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -326,8 +361,10 @@ static int dumpStdIntVector()
|
||||
static int dumpStdStringVector()
|
||||
{
|
||||
std::vector<std::string> test;
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
if (!optEmptyContainers) {
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
}
|
||||
prepareInBuffer("std::vector", "local.stringvector", "local.stringvector", "std::string");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -338,8 +375,10 @@ static int dumpStdStringVector()
|
||||
static int dumpStdWStringVector()
|
||||
{
|
||||
std::vector<std::wstring> test;
|
||||
test.push_back(L"item1");
|
||||
test.push_back(L"item2");
|
||||
if (!optEmptyContainers) {
|
||||
test.push_back(L"item1");
|
||||
test.push_back(L"item2");
|
||||
}
|
||||
prepareInBuffer("std::vector", "local.wstringvector", "local.wstringvector", "std::wstring");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::wstring), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -350,8 +389,10 @@ static int dumpStdWStringVector()
|
||||
static int dumpStdIntSet()
|
||||
{
|
||||
std::set<int> test;
|
||||
test.insert(1);
|
||||
test.insert(2);
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(1);
|
||||
test.insert(2);
|
||||
}
|
||||
prepareInBuffer("std::set", "local.intset", "local.intset", "int");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -362,8 +403,10 @@ static int dumpStdIntSet()
|
||||
static int dumpStdStringSet()
|
||||
{
|
||||
std::set<std::string> test;
|
||||
test.insert("item1");
|
||||
test.insert("item2");
|
||||
if (!optEmptyContainers) {
|
||||
test.insert("item1");
|
||||
test.insert("item2");
|
||||
}
|
||||
prepareInBuffer("std::set", "local.stringset", "local.stringset", "std::string");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -374,8 +417,10 @@ static int dumpStdStringSet()
|
||||
static int dumpStdQStringSet()
|
||||
{
|
||||
std::set<QString> test;
|
||||
test.insert(QLatin1String("item1"));
|
||||
test.insert(QLatin1String("item2"));
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(QLatin1String("item1"));
|
||||
test.insert(QLatin1String("item2"));
|
||||
}
|
||||
prepareInBuffer("std::set", "local.stringset", "local.stringset", "QString");
|
||||
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
@@ -385,9 +430,11 @@ static int dumpStdQStringSet()
|
||||
|
||||
static int dumpStdMapIntString()
|
||||
{
|
||||
std::map<int,std::string> test;
|
||||
std::map<int,std::string> test;
|
||||
std::map<int,std::string>::value_type entry(42, std::string("fortytwo"));
|
||||
test.insert(entry);
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(entry);
|
||||
}
|
||||
const int valueOffset = (char*)&(entry.second) - (char*)&entry;
|
||||
prepareInBuffer("std::map", "local.stdmapintstring", "local.stdmapintstring",
|
||||
"int@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const int,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >");
|
||||
@@ -402,7 +449,9 @@ static int dumpStdMapStringString()
|
||||
typedef std::map<std::string,std::string> TestType;
|
||||
TestType test;
|
||||
const TestType::value_type entry("K", "V");
|
||||
test.insert(entry);
|
||||
if (!optEmptyContainers) {
|
||||
test.insert(entry);
|
||||
}
|
||||
const int valueOffset = (char*)&(entry.second) - (char*)&entry;
|
||||
prepareInBuffer("std::map", "local.stdmapstringstring", "local.stdmapstringstring",
|
||||
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >");
|
||||
@@ -502,6 +551,23 @@ static TypeDumpFunctionMap registerTypes()
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void usage(const char *b, const TypeDumpFunctionMap &tdm)
|
||||
{
|
||||
printf("Usage: %s [-v][-u][-e] <type1> <type2..>\n", b);
|
||||
printf("Usage: %s [-v][-u][-e] -a excluded_type1 <excluded_type2...>\n", b);
|
||||
printf("Options: -u Test uninitialized memory\n");
|
||||
printf(" -e Empty containers\n");
|
||||
printf(" -v Verbose\n");
|
||||
printf(" -a Test all available types\n");
|
||||
printf("Supported types: ");
|
||||
const TypeDumpFunctionMap::const_iterator cend = tdm.constEnd();
|
||||
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
|
||||
fputs(qPrintable(it.key()), stdout);
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("\nQt Creator Debugging Helper testing tool\n\n");
|
||||
@@ -515,30 +581,57 @@ int main(int argc, char *argv[])
|
||||
const TypeDumpFunctionMap::const_iterator cend = tdm.constEnd();
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s [-a]|<type1> <type2..>\n", argv[0]);
|
||||
printf("Supported types: ");
|
||||
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
|
||||
fputs(qPrintable(it.key()), stdout);
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
usage(argv[0], tdm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse args
|
||||
QStringList tests;
|
||||
for (int a = 1; a < argc; a++) {
|
||||
const char *arg = argv[a];
|
||||
if (arg[0] == '-') {
|
||||
switch (arg[1]) {
|
||||
case 'a':
|
||||
optTestAll = true;
|
||||
break;
|
||||
case 'u':
|
||||
optTestUninitialized = true;
|
||||
break;
|
||||
case 'v':
|
||||
optVerbose++;
|
||||
break;
|
||||
case 'e':
|
||||
optEmptyContainers = true;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid option %s\n", arg);
|
||||
usage(argv[0], tdm);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
tests.push_back(QLatin1String(arg));
|
||||
}
|
||||
}
|
||||
// Go
|
||||
int rc = 0;
|
||||
if (argc == 2 && !qstrcmp(argv[1], "-a")) {
|
||||
if (optTestAll) {
|
||||
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
|
||||
printf("\nTesting: %s\n", qPrintable(it.key()));
|
||||
rc += (*it.value())();
|
||||
const QString test = it.key();
|
||||
if (tests.contains(test)) {
|
||||
printf("\nSkipping: %s\n", qPrintable(test));
|
||||
} else {
|
||||
printf("\nTesting: %s\n", qPrintable(test));
|
||||
rc += (*it.value())();
|
||||
if (optTestUninitialized)
|
||||
printf("Survived: %s\n", qPrintable(test));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
printf("\nTesting: %s\n", arg);
|
||||
const TypeDumpFunctionMap::const_iterator it = tdm.constFind(QLatin1String(arg));
|
||||
foreach(const QString &test, tests) {
|
||||
printf("\nTesting: %s\n", qPrintable(test));
|
||||
const TypeDumpFunctionMap::const_iterator it = tdm.constFind(test);
|
||||
if (it == cend) {
|
||||
rc = -1;
|
||||
fprintf(stderr, "\nUnhandled type: %s\n", argv[i]);
|
||||
fprintf(stderr, "\nUnhandled type: %s\n", qPrintable(test));
|
||||
} else {
|
||||
rc = (*it.value())();
|
||||
}
|
||||
|
@@ -565,63 +565,63 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
|
||||
const QChar ch3 = pos > 1 ? editor->characterAt(pos - 3) : QChar();
|
||||
|
||||
int start = pos;
|
||||
int k = T_EOF_SYMBOL;
|
||||
int completionKind = T_EOF_SYMBOL;
|
||||
|
||||
switch (ch.toLatin1()) {
|
||||
case '.':
|
||||
if (ch2 != QLatin1Char('.')) {
|
||||
k = T_DOT;
|
||||
completionKind = T_DOT;
|
||||
--start;
|
||||
}
|
||||
break;
|
||||
case ',':
|
||||
k = T_COMMA;
|
||||
completionKind = T_COMMA;
|
||||
--start;
|
||||
break;
|
||||
case '(':
|
||||
if (wantFunctionCall) {
|
||||
k = T_LPAREN;
|
||||
completionKind = T_LPAREN;
|
||||
--start;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
if (ch3 != QLatin1Char(':') && ch2 == QLatin1Char(':')) {
|
||||
k = T_COLON_COLON;
|
||||
completionKind = T_COLON_COLON;
|
||||
start -= 2;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (ch2 == QLatin1Char('-')) {
|
||||
k = T_ARROW;
|
||||
completionKind = T_ARROW;
|
||||
start -= 2;
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
if (ch2 == QLatin1Char('.')) {
|
||||
k = T_DOT_STAR;
|
||||
completionKind = T_DOT_STAR;
|
||||
start -= 2;
|
||||
} else if (ch3 == QLatin1Char('-') && ch2 == QLatin1Char('>')) {
|
||||
k = T_ARROW_STAR;
|
||||
completionKind = T_ARROW_STAR;
|
||||
start -= 3;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
case '@':
|
||||
if (ch2.isNull() || ch2.isSpace()) {
|
||||
k = T_DOXY_COMMENT;
|
||||
completionKind = T_DOXY_COMMENT;
|
||||
--start;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
k = T_ANGLE_STRING_LITERAL;
|
||||
completionKind = T_ANGLE_STRING_LITERAL;
|
||||
--start;
|
||||
break;
|
||||
case '"':
|
||||
k = T_STRING_LITERAL;
|
||||
completionKind = T_STRING_LITERAL;
|
||||
--start;
|
||||
break;
|
||||
case '/':
|
||||
k = T_SLASH;
|
||||
completionKind = T_SLASH;
|
||||
--start;
|
||||
break;
|
||||
}
|
||||
@@ -634,20 +634,20 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
|
||||
tc.setPosition(pos);
|
||||
|
||||
// Include completion: make sure the quote character is the first one on the line
|
||||
if (k == T_STRING_LITERAL) {
|
||||
if (completionKind == T_STRING_LITERAL) {
|
||||
QTextCursor s = tc;
|
||||
s.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
|
||||
QString sel = s.selectedText();
|
||||
if (sel.indexOf(QLatin1Char('"')) < sel.length() - 1) {
|
||||
k = T_EOF_SYMBOL;
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (k == T_COMMA) {
|
||||
if (completionKind == T_COMMA) {
|
||||
ExpressionUnderCursor expressionUnderCursor;
|
||||
if (expressionUnderCursor.startOfFunctionCall(tc) == -1) {
|
||||
k = T_EOF_SYMBOL;
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
}
|
||||
@@ -655,24 +655,24 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
|
||||
static CPlusPlus::TokenUnderCursor tokenUnderCursor;
|
||||
const SimpleToken tk = tokenUnderCursor(tc);
|
||||
|
||||
if (k == T_DOXY_COMMENT && tk.isNot(T_DOXY_COMMENT)) {
|
||||
k = T_EOF_SYMBOL;
|
||||
if (completionKind == T_DOXY_COMMENT && !(tk.is(T_DOXY_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))) {
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
// Don't complete in comments or strings, but still check for include completion
|
||||
else if (tk.is(T_COMMENT) || (tk.isLiteral() &&
|
||||
(k != T_STRING_LITERAL
|
||||
&& k != T_ANGLE_STRING_LITERAL
|
||||
&& k != T_SLASH))) {
|
||||
k = T_EOF_SYMBOL;
|
||||
else if (tk.is(T_COMMENT) || tk.is(T_CPP_COMMENT) ||
|
||||
(tk.isLiteral() && (completionKind != T_STRING_LITERAL
|
||||
&& completionKind != T_ANGLE_STRING_LITERAL
|
||||
&& completionKind != T_SLASH))) {
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
// Include completion: can be triggered by slash, but only in a string
|
||||
else if (k == T_SLASH && (tk.isNot(T_STRING_LITERAL) && tk.isNot(T_ANGLE_STRING_LITERAL))) {
|
||||
k = T_EOF_SYMBOL;
|
||||
else if (completionKind == T_SLASH && (tk.isNot(T_STRING_LITERAL) && tk.isNot(T_ANGLE_STRING_LITERAL))) {
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
else if (k == T_LPAREN) {
|
||||
else if (completionKind == T_LPAREN) {
|
||||
const QList<SimpleToken> &tokens = tokenUnderCursor.tokens();
|
||||
int i = 0;
|
||||
for (; i < tokens.size(); ++i) {
|
||||
@@ -688,12 +688,12 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
|
||||
}
|
||||
|
||||
if (i == tokens.size()) {
|
||||
k = T_EOF_SYMBOL;
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
}
|
||||
// Check for include preprocessor directive
|
||||
else if (k == T_STRING_LITERAL || k == T_ANGLE_STRING_LITERAL || k == T_SLASH) {
|
||||
else if (completionKind == T_STRING_LITERAL || completionKind == T_ANGLE_STRING_LITERAL || completionKind == T_SLASH) {
|
||||
bool include = false;
|
||||
const QList<SimpleToken> &tokens = tokenUnderCursor.tokens();
|
||||
if (tokens.size() >= 3) {
|
||||
@@ -709,13 +709,13 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
|
||||
}
|
||||
|
||||
if (!include) {
|
||||
k = T_EOF_SYMBOL;
|
||||
completionKind = T_EOF_SYMBOL;
|
||||
start = pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (kind)
|
||||
*kind = k;
|
||||
*kind = completionKind;
|
||||
|
||||
return start;
|
||||
}
|
||||
@@ -1022,8 +1022,13 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
||||
|
||||
// find a scope that encloses the current location, starting from the lastVisibileSymbol
|
||||
// and moving outwards
|
||||
Scope *sc = context.symbol()->scope();
|
||||
while (sc->enclosingScope()) {
|
||||
Scope *sc = 0;
|
||||
if (context.symbol())
|
||||
sc = context.symbol()->scope();
|
||||
else if (context.thisDocument())
|
||||
sc = context.thisDocument()->globalSymbols();
|
||||
|
||||
while (sc && sc->enclosingScope()) {
|
||||
unsigned startLine, startColumn;
|
||||
context.thisDocument()->translationUnit()->getPosition(sc->owner()->startOffset(), &startLine, &startColumn);
|
||||
unsigned endLine, endColumn;
|
||||
@@ -1037,7 +1042,7 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
||||
sc = sc->enclosingScope();
|
||||
}
|
||||
|
||||
if (sc->isClassScope() || sc->isNamespaceScope())
|
||||
if (sc && (sc->isClassScope() || sc->isNamespaceScope()))
|
||||
{
|
||||
// It may still be a function call. If the whole line parses as a function
|
||||
// declaration, we should be certain that it isn't.
|
||||
@@ -1066,10 +1071,18 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
|
||||
Overview overview;
|
||||
overview.setShowArgumentNames(true);
|
||||
|
||||
TextEditor::CompletionItem item(this);
|
||||
item.text = overview(f->type());
|
||||
item.text = item.text.mid(1, item.text.size()-2);
|
||||
m_completions.append(item);
|
||||
// get rid of parentheses and cv-qualifiers
|
||||
QString completion = overview(f->type());
|
||||
if (f->isVolatile() || f->isConst())
|
||||
completion = completion.mid(1, completion.lastIndexOf(')') - 1);
|
||||
else
|
||||
completion = completion.mid(1, completion.size() - 2);
|
||||
|
||||
if (completion.size()) {
|
||||
TextEditor::CompletionItem item(this);
|
||||
item.text = completion;
|
||||
m_completions.append(item);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -707,10 +707,17 @@ bool CdbDebugEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QStri
|
||||
{
|
||||
// Need to attrach invasively, otherwise, no notification signals
|
||||
// for for CreateProcess/ExitProcess occur.
|
||||
// As of version 6.11, the initial breakpoint suppression has no effect (see notifyException).
|
||||
// when attaching to a console process starting up. However, there is no initial breakpoint
|
||||
// (and no startup trap), when attaching to a running GUI process.
|
||||
const ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS|DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK;
|
||||
// Initial breakpoint occur:
|
||||
// 1) Desired: When attaching to a crashed process
|
||||
// 2) Undesired: When starting up a console process, in conjunction
|
||||
// with the 32bit Wow-engine
|
||||
// As of version 6.11, the flag only affects 1). 2) Still needs to be suppressed
|
||||
// by lookup at the state of the application (startup trap). However,
|
||||
// there is no startup trap when attaching to a process that has been
|
||||
// running for a while. (see notifyException).
|
||||
ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS;
|
||||
if (manager()->startParameters()->startMode != AttachCrashedExternal)
|
||||
flags |= DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK;
|
||||
const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid, flags);
|
||||
if (debugCDB)
|
||||
qDebug() << "Attaching to " << pid << " using flags" << flags << " returns " << hr << executionStatusString(m_d->m_cif.debugControl);
|
||||
@@ -817,6 +824,9 @@ void CdbDebugEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG6
|
||||
void CdbDebugEngine::processTerminated(unsigned long exitCode)
|
||||
{
|
||||
manager()->showDebuggerOutput(LogMisc, tr("The process exited with exit code %1.").arg(exitCode));
|
||||
if (state() != InferiorStopping)
|
||||
setState(InferiorStopping, Q_FUNC_INFO, __LINE__);
|
||||
setState(InferiorStopped, Q_FUNC_INFO, __LINE__);
|
||||
setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__);
|
||||
m_d->setDebuggeeHandles(0, 0);
|
||||
m_d->clearForRun();
|
||||
@@ -912,14 +922,11 @@ void CdbDebugEnginePrivate::endDebugging(EndDebuggingMode em)
|
||||
errorMessage.clear();
|
||||
}
|
||||
// Clean up resources (open files, etc.)
|
||||
m_engine->setState(AdapterShuttingDown, Q_FUNC_INFO, __LINE__);
|
||||
m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__);
|
||||
clearForRun();
|
||||
const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE);
|
||||
if (SUCCEEDED(hr)) {
|
||||
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
|
||||
} else {
|
||||
m_engine->setState(AdapterShutdownFailed, Q_FUNC_INFO, __LINE__);
|
||||
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
|
||||
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr));
|
||||
manager()->showDebuggerOutput(LogError, errorMessage);
|
||||
}
|
||||
|
@@ -341,6 +341,8 @@ void CdbDumperInitThread ::run()
|
||||
CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager,
|
||||
CdbComInterfaces *cif) :
|
||||
m_tryInjectLoad(true),
|
||||
m_msgDisabled(QLatin1String("Dumpers are disabled")),
|
||||
m_msgNotInScope(QLatin1String("Data not in scope")),
|
||||
m_state(NotLoaded),
|
||||
m_manager(manager),
|
||||
m_cif(cif),
|
||||
@@ -561,8 +563,14 @@ CdbDumperHelper::CallResult
|
||||
if (!writeToDebuggee(m_cif->debugDataSpaces, inBuffer, m_inBufferAddress, errorMessage))
|
||||
return CallFailed;
|
||||
}
|
||||
if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, callCmd, errorMessage))
|
||||
if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, callCmd, errorMessage)) {
|
||||
// Clear the outstanding call in case we triggered a debug library assert with a message box
|
||||
QString clearError;
|
||||
if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, QLatin1String(".call /c"), &clearError)) {
|
||||
*errorMessage += QString::fromLatin1("/Unable to clear call %1").arg(clearError);
|
||||
}
|
||||
return CallSyntaxError;
|
||||
}
|
||||
// Set up call and a temporary breakpoint after it.
|
||||
// Try to skip debuggee crash exceptions and dumper exceptions
|
||||
// by using 'gN' (go not handled -> pass handling to dumper __try/__catch block)
|
||||
@@ -648,8 +656,12 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpTypeI(const WatchData &wd, bool
|
||||
{
|
||||
errorMessage->clear();
|
||||
// Check failure cache and supported types
|
||||
if (m_state == Disabled) {
|
||||
*errorMessage = QLatin1String("Dumpers are disabled");
|
||||
if (m_state == Disabled) {
|
||||
*errorMessage =m_msgDisabled;
|
||||
return DumpNotHandled;
|
||||
}
|
||||
if (wd.error) {
|
||||
*errorMessage =m_msgNotInScope;
|
||||
return DumpNotHandled;
|
||||
}
|
||||
if (m_failedTypes.contains(wd.type)) {
|
||||
|
@@ -134,6 +134,8 @@ private:
|
||||
static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage);
|
||||
|
||||
const bool m_tryInjectLoad;
|
||||
const QString m_msgDisabled;
|
||||
const QString m_msgNotInScope;
|
||||
State m_state;
|
||||
DebuggerManager *m_manager;
|
||||
CdbComInterfaces *m_cif;
|
||||
|
@@ -217,7 +217,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
|
||||
|
||||
bool handled = false;
|
||||
do {
|
||||
if (!isPointerType(wd.type))
|
||||
if (wd.error || !isPointerType(wd.type))
|
||||
break;
|
||||
const int classPos = wd.value.indexOf(" class ");
|
||||
if (classPos == -1)
|
||||
@@ -396,9 +396,9 @@ bool CdbStackFrameContext::editorToolTip(const QString &iname,
|
||||
*errorMessage = QString::fromLatin1("%1 not found.").arg(iname);
|
||||
return false;
|
||||
}
|
||||
const WatchData wd = m_symbolContext->symbolAt(index);
|
||||
// Check dumpers. Should actually be just one item.
|
||||
if (m_useDumpers && m_dumper->state() != CdbDumperHelper::Disabled) {
|
||||
const WatchData wd = m_symbolContext->watchDataAt(index);
|
||||
if (m_useDumpers && !wd.error && m_dumper->state() != CdbDumperHelper::Disabled) {
|
||||
QList<WatchData> result;
|
||||
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, &result, errorMessage)) {
|
||||
foreach (const WatchData &dwd, result) {
|
||||
|
@@ -33,8 +33,11 @@
|
||||
#include "cdbsymbolgroupcontext.h"
|
||||
#include "cdbdebugengine_p.h"
|
||||
#include "cdbdumperhelper.h"
|
||||
#include "debuggeractions.h"
|
||||
#include "debuggermanager.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
namespace Debugger {
|
||||
@@ -85,6 +88,7 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
|
||||
if (debugCDB)
|
||||
qDebug() << Q_FUNC_INFO << frameCount;
|
||||
|
||||
const QChar exclamationMark = QLatin1Char('!');
|
||||
m_frameContexts.resize(frameCount);
|
||||
qFill(m_frameContexts, static_cast<CdbStackFrameContext*>(0));
|
||||
|
||||
@@ -99,7 +103,11 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
|
||||
frame.address = QString::fromLatin1("0x%1").arg(instructionOffset, 0, 16);
|
||||
|
||||
m_cif->debugSymbols->GetNameByOffsetWide(instructionOffset, wszBuf, MAX_PATH, 0, 0);
|
||||
// Determine function and module, if available
|
||||
frame.function = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf));
|
||||
const int moduleSepPos = frame.function.indexOf(exclamationMark);
|
||||
if (moduleSepPos != -1)
|
||||
frame.from = frame.function.mid(0, moduleSepPos);
|
||||
|
||||
ULONG ulLine;
|
||||
ULONG64 ul64Displacement;
|
||||
@@ -160,7 +168,13 @@ CdbStackFrameContext *CdbStackTraceContext::frameContextAt(int index, QString *e
|
||||
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
|
||||
return 0;
|
||||
}
|
||||
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, errorMessage);
|
||||
// Exclude unitialized variables if desired
|
||||
QStringList uninitializedVariables;
|
||||
if (theDebuggerAction(UseCodeModel)->isChecked()) {
|
||||
const StackFrame &frame = m_frames.at(index);
|
||||
getUninitializedVariables(DebuggerManager::instance()->cppCodeModelSnapshot(), frame.function, frame.file, frame.line, &uninitializedVariables);
|
||||
}
|
||||
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, uninitializedVariables, errorMessage);
|
||||
if (!sc) {
|
||||
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
|
||||
return 0;
|
||||
|
@@ -39,6 +39,9 @@
|
||||
enum { debug = 0 };
|
||||
enum { debugInternalDumpers = 0 };
|
||||
|
||||
// name separator for shadowed variables
|
||||
static const char iNameShadowDelimiter = '#';
|
||||
|
||||
static inline QString msgSymbolNotFound(const QString &s)
|
||||
{
|
||||
return QString::fromLatin1("The symbol '%1' could not be found.").arg(s);
|
||||
@@ -83,6 +86,14 @@ QTextStream &operator<<(QTextStream &str, const DEBUG_SYMBOL_PARAMETERS &p)
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
|
||||
{
|
||||
ULONG64 rc = 0;
|
||||
if (FAILED(sg->GetSymbolOffset(index, &rc)))
|
||||
rc = 0;
|
||||
return QLatin1String("0x") + QString::number(rc, 16);
|
||||
}
|
||||
|
||||
// A helper function to extract a string value from a member function of
|
||||
// IDebugSymbolGroup2 taking the symbol index and a character buffer.
|
||||
// Pass in the the member function as '&IDebugSymbolGroup2::GetSymbolNameWide'
|
||||
@@ -129,12 +140,15 @@ static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMB
|
||||
}
|
||||
|
||||
CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix,
|
||||
CIDebugSymbolGroup *symbolGroup) :
|
||||
CIDebugSymbolGroup *symbolGroup,
|
||||
const QStringList &uninitializedVariables) :
|
||||
m_prefix(prefix),
|
||||
m_nameDelimiter(QLatin1Char('.')),
|
||||
m_uninitializedVariables(uninitializedVariables.toSet()),
|
||||
m_symbolGroup(symbolGroup),
|
||||
m_unnamedSymbolNumber(1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CdbSymbolGroupContext::~CdbSymbolGroupContext()
|
||||
@@ -144,9 +158,10 @@ CdbSymbolGroupContext::~CdbSymbolGroupContext()
|
||||
|
||||
CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix,
|
||||
CIDebugSymbolGroup *symbolGroup,
|
||||
const QStringList &uninitializedVariables,
|
||||
QString *errorMessage)
|
||||
{
|
||||
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup);
|
||||
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup, uninitializedVariables);
|
||||
if (!rc->init(errorMessage)) {
|
||||
delete rc;
|
||||
return 0;
|
||||
@@ -173,28 +188,36 @@ bool CdbSymbolGroupContext::init(QString *errorMessage)
|
||||
*errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO), msgComFailed("GetSymbolParameters", hr)).arg(count);
|
||||
return false;
|
||||
}
|
||||
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, 0, count);
|
||||
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, count);
|
||||
}
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << '\n'<< toString();
|
||||
qDebug() << Q_FUNC_INFO << '\n'<< toString(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Make the entries for iname->index mapping. We might encounter
|
||||
* already expanded subitems when doing it for top-level ('this'-pointers),
|
||||
* recurse in that case, (skip over expanded children).
|
||||
* Loop backwards to detect shadowed variables in the order the
|
||||
/* debugger expects them:
|
||||
\code
|
||||
int x; // Occurrence (1), should be reported as "x <shadowed 1>"
|
||||
if (true) {
|
||||
int x = 5; (2) // Occurrence (2), should be reported as "x"
|
||||
}
|
||||
\endcode
|
||||
* The order in the symbol group is (1),(2). Give them an iname of
|
||||
* <root>#<shadowed-nr>, which will be split apart for display. */
|
||||
|
||||
void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigned long parentId,
|
||||
unsigned long start, unsigned long count)
|
||||
unsigned long end)
|
||||
{
|
||||
// Make the entries for iname->index mapping. We might encounter
|
||||
// already expanded subitems when doing it for top-level, recurse in that case.
|
||||
const QString symbolPrefix = prefix + m_nameDelimiter;
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << start << count;
|
||||
const unsigned long end = m_symbolParameters.size();
|
||||
unsigned long seenChildren = 0;
|
||||
// Skip over expanded children
|
||||
for (unsigned long i = start; i < end && seenChildren < count; i++) {
|
||||
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << parentId << end;
|
||||
for (unsigned long i = end - 1; ; i--) {
|
||||
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i);
|
||||
if (parentId == p.ParentSymbol) {
|
||||
seenChildren++;
|
||||
// "__formal" occurs when someone writes "void foo(int /* x */)..."
|
||||
static const QString unnamedFormalParameter = QLatin1String("__formal");
|
||||
QString symbolName = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
|
||||
@@ -203,11 +226,21 @@ void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigne
|
||||
symbolName += QString::number(m_unnamedSymbolNumber++);
|
||||
symbolName += QLatin1Char('>');
|
||||
}
|
||||
const QString name = symbolPrefix + symbolName;
|
||||
// Find a unique name in case the variable is shadowed by
|
||||
// an existing one
|
||||
const QString namePrefix = symbolPrefix + symbolName;
|
||||
QString name = namePrefix;
|
||||
for (int n = 1; m_inameIndexMap.contains(name); n++) {
|
||||
name.truncate(namePrefix.size());
|
||||
name += QLatin1Char(iNameShadowDelimiter);
|
||||
name += QString::number(n);
|
||||
}
|
||||
m_inameIndexMap.insert(name, i);
|
||||
if (getSymbolState(p) == ExpandedSymbol)
|
||||
populateINameIndexMap(name, i, i + 1, p.SubElements);
|
||||
populateINameIndexMap(name, i, i + 1 + p.SubElements);
|
||||
}
|
||||
if (i == 0 || i == parentId)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +256,10 @@ QString CdbSymbolGroupContext::toString(bool verbose) const
|
||||
str << " ";
|
||||
str << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
|
||||
if (p.Flags & DEBUG_SYMBOL_IS_LOCAL)
|
||||
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i);
|
||||
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i) << '\'';
|
||||
str << " Address: " << hexSymbolOffset(m_symbolGroup, i);
|
||||
if (verbose)
|
||||
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, i) << '\'';
|
||||
str << p << '\n';
|
||||
}
|
||||
if (verbose) {
|
||||
@@ -348,7 +384,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
|
||||
if (it.value() > index)
|
||||
it.value() += newSymbolCount;
|
||||
// insert the new symbols
|
||||
populateINameIndexMap(prefix, index, index + 1, newSymbolCount);
|
||||
populateINameIndexMap(prefix, index, index + 1 + newSymbolCount);
|
||||
if (debug > 1)
|
||||
qDebug() << '<' << Q_FUNC_INFO << '\n' << prefix << index << '\n' << toString();
|
||||
return true;
|
||||
@@ -365,14 +401,6 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
|
||||
return m_inameIndexMap.key(index);
|
||||
}
|
||||
|
||||
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
|
||||
{
|
||||
ULONG64 rc = 0;
|
||||
if (FAILED(sg->GetSymbolOffset(index, &rc)))
|
||||
rc = 0;
|
||||
return QLatin1String("0x") + QString::number(rc, 16);
|
||||
}
|
||||
|
||||
// check for "0x000", "0x000 class X"
|
||||
static inline bool isNullPointer(const WatchData &wd)
|
||||
{
|
||||
@@ -409,19 +437,35 @@ static inline QString fixValue(const QString &value)
|
||||
return removeInnerTemplateType(value);
|
||||
}
|
||||
|
||||
WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
|
||||
WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
|
||||
{
|
||||
WatchData wd;
|
||||
wd.iname = symbolINameAt(index);
|
||||
wd.exp = wd.iname;
|
||||
// Determine name from iname and format shadowed variables correctly
|
||||
// as "<shadowed X>, see populateINameIndexMap().
|
||||
const int lastDelimiterPos = wd.iname.lastIndexOf(m_nameDelimiter);
|
||||
QString name = lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1);
|
||||
int shadowedNumber = 0;
|
||||
const int shadowedPos = name.lastIndexOf(QLatin1Char(iNameShadowDelimiter));
|
||||
if (shadowedPos != -1) {
|
||||
shadowedNumber = name.mid(shadowedPos + 1).toInt();
|
||||
name.truncate(shadowedPos);
|
||||
}
|
||||
// For class hierarchies, we get sometimes complicated std::template types here.
|
||||
// Remove them for display
|
||||
wd.name = removeInnerTemplateType(lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1));
|
||||
// (std::map extends std::tree<>... Remove them for display only.
|
||||
const QString fullShadowedName = WatchData::shadowedName(name, shadowedNumber);
|
||||
wd.name = WatchData::shadowedName(removeInnerTemplateType(name), shadowedNumber);
|
||||
wd.addr = hexSymbolOffset(m_symbolGroup, index);
|
||||
const QString type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index);
|
||||
const QString type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index);
|
||||
wd.setType(type);
|
||||
// Check for unitialized variables at level 0 only.
|
||||
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(index);
|
||||
if (p.ParentSymbol == DEBUG_ANY_ID && m_uninitializedVariables.contains(fullShadowedName)) {
|
||||
wd.setError(WatchData::msgNotInScope());
|
||||
return wd;
|
||||
}
|
||||
const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
|
||||
wd.setType(type);
|
||||
wd.setValue(fixValue(value));
|
||||
wd.setChildrenNeeded(); // compensate side effects of above setters
|
||||
// Figure out children. The SubElement is only a guess unless the symbol,
|
||||
@@ -429,7 +473,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
|
||||
// If the symbol has children (expanded or not), we leave the 'Children' flag
|
||||
// in 'needed' state. Suppress 0-pointers right ("0x000 class X")
|
||||
// here as they only lead to children with memory access errors.
|
||||
const bool hasChildren = m_symbolParameters.at(index).SubElements && !isNullPointer(wd);
|
||||
const bool hasChildren = p.SubElements && !isNullPointer(wd);
|
||||
wd.setHasChildren(hasChildren);
|
||||
if (debug > 1)
|
||||
qDebug() << Q_FUNC_INFO << index << '\n' << wd.toString();
|
||||
@@ -438,7 +482,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
|
||||
|
||||
WatchData CdbSymbolGroupContext::dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index)
|
||||
{
|
||||
WatchData rc = symbolAt(index);
|
||||
WatchData rc = watchDataAt(index);
|
||||
dump(ds, &rc);
|
||||
return rc;
|
||||
}
|
||||
|
@@ -69,12 +69,14 @@ class CdbSymbolGroupContext
|
||||
{
|
||||
Q_DISABLE_COPY(CdbSymbolGroupContext);
|
||||
explicit CdbSymbolGroupContext(const QString &prefix,
|
||||
CIDebugSymbolGroup *symbolGroup);
|
||||
CIDebugSymbolGroup *symbolGroup,
|
||||
const QStringList &uninitializedVariables = QStringList());
|
||||
|
||||
public:
|
||||
~CdbSymbolGroupContext();
|
||||
static CdbSymbolGroupContext *create(const QString &prefix,
|
||||
static CdbSymbolGroupContext *create(const QString &prefix,
|
||||
CIDebugSymbolGroup *symbolGroup,
|
||||
const QStringList &uninitializedVariables,
|
||||
QString *errorMessage);
|
||||
|
||||
QString prefix() const { return m_prefix; }
|
||||
@@ -118,7 +120,7 @@ public:
|
||||
int dumpedOwner,
|
||||
OutputIterator it, QString *errorMessage);
|
||||
|
||||
WatchData symbolAt(unsigned long index) const;
|
||||
WatchData watchDataAt(unsigned long index) const;
|
||||
// Run the internal dumpers on the symbol
|
||||
WatchData dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index);
|
||||
|
||||
@@ -155,7 +157,7 @@ private:
|
||||
unsigned long *parentId,
|
||||
QString *errorMessage);
|
||||
bool expandSymbol(const QString &prefix, unsigned long index, QString *errorMessage);
|
||||
void populateINameIndexMap(const QString &prefix, unsigned long parentId, unsigned long start, unsigned long count);
|
||||
void populateINameIndexMap(const QString &prefix, unsigned long parentId, unsigned long end);
|
||||
QString symbolINameAt(unsigned long index) const;
|
||||
|
||||
int dumpQString(CIDebugDataSpaces *ds, WatchData *wd);
|
||||
@@ -166,6 +168,7 @@ private:
|
||||
|
||||
const QString m_prefix;
|
||||
const QChar m_nameDelimiter;
|
||||
const QSet<QString> m_uninitializedVariables;
|
||||
|
||||
CIDebugSymbolGroup *m_symbolGroup;
|
||||
NameIndexMap m_inameIndexMap;
|
||||
|
@@ -61,7 +61,7 @@ bool CdbSymbolGroupContext::getDumpChildSymbols(CIDebugDataSpaces *ds, const QSt
|
||||
for (int s = start; s < m_symbolParameters.size(); ++s) {
|
||||
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s);
|
||||
if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) {
|
||||
WatchData wd = symbolAt(s);
|
||||
WatchData wd = watchDataAt(s);
|
||||
// Run internal dumper, mark ownership
|
||||
if (ds) {
|
||||
switch (dump(ds, &wd)) {
|
||||
|
@@ -229,6 +229,13 @@ DebuggerSettings *DebuggerSettings::instance()
|
||||
item->setValue(false);
|
||||
instance->insertItem(DebugDebuggingHelpers, item);
|
||||
|
||||
item = new SavedAction(instance);
|
||||
item->setSettingsKey(debugModeGroup, QLatin1String("UseCodeModel"));
|
||||
item->setText(tr("Use code model"));
|
||||
item->setCheckable(true);
|
||||
item->setDefaultValue(false);
|
||||
item->setValue(false);
|
||||
instance->insertItem(UseCodeModel, item);
|
||||
|
||||
item = new SavedAction(instance);
|
||||
item->setText(tr("Recheck debugging helper availability"));
|
||||
|
@@ -85,6 +85,8 @@ enum DebuggerActionCode
|
||||
UseCustomDebuggingHelperLocation,
|
||||
CustomDebuggingHelperLocation,
|
||||
DebugDebuggingHelpers,
|
||||
|
||||
UseCodeModel,
|
||||
|
||||
UseToolTipsInMainEditor,
|
||||
UseToolTipsInLocalsView,
|
||||
|
@@ -79,15 +79,13 @@ enum DebuggerState
|
||||
|
||||
InferiorStopping, // Debuggee running, stop requested
|
||||
InferiorStopped, // Debuggee stopped
|
||||
InferiorStopFailed, // Debuggee stopped
|
||||
InferiorStopFailed, // Debuggee not stopped, will kill debugger
|
||||
|
||||
InferiorShuttingDown,
|
||||
InferiorShutDown,
|
||||
InferiorShutdownFailed,
|
||||
|
||||
AdapterShuttingDown,
|
||||
//AdapterShutDown, // Use DebuggerNotReady instead
|
||||
AdapterShutdownFailed,
|
||||
EngineShuttingDown
|
||||
};
|
||||
|
||||
enum DebuggerStartMode
|
||||
|
@@ -61,6 +61,8 @@
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
#include <cplusplus/CppDocument.h>
|
||||
#include <cpptools/cppmodelmanagerinterface.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
@@ -99,43 +101,35 @@
|
||||
// gdbserver, the trk client etc are referred to as 'Adapter',
|
||||
// whereas the debugged process is referred to as 'Inferior'.
|
||||
//
|
||||
// 0 == DebuggerNotReady
|
||||
// 0 == DebuggerNotReady
|
||||
// |
|
||||
// EngineStarting
|
||||
// EngineStarting
|
||||
// |
|
||||
// AdapterStarting --> AdapterStartFailed --> 0
|
||||
// AdapterStarting --> AdapterStartFailed --> 0
|
||||
// |
|
||||
// AdapterStarted
|
||||
// |
|
||||
// InferiorStarting --> InferiorStartFailed --> 0
|
||||
// |
|
||||
// (core) | (attach) (remote)
|
||||
// .-----------------<-|->--------------------.
|
||||
// | v |
|
||||
// InferiorUnrunnable | |
|
||||
// | | v
|
||||
// | | (plain)
|
||||
// | | (trk)
|
||||
// | |
|
||||
// | | .------------------------------------.
|
||||
// | | v |
|
||||
// | InferiorRunningRequested v |
|
||||
// | | | |
|
||||
// | .---- InferiorRunning | |
|
||||
// | | | | |
|
||||
// | | InferiorStopping | |
|
||||
// | | | | |
|
||||
// | v v | |
|
||||
// | |<--- InferiorStopped <-----------' |
|
||||
// | | | |
|
||||
// | | `---------------------------------------'
|
||||
// | |
|
||||
// | '---> InferiorShuttingDown -> InferiorShutdownFailed
|
||||
// | |
|
||||
// | InferiorShutDown
|
||||
// | |
|
||||
// | v
|
||||
// '------------> AdapterShuttingDown -> AdapterShutdownFailed --> 0
|
||||
// AdapterStarted ------------------------------------.
|
||||
// | v
|
||||
// InferiorStarting ----> InferiorStartFailed -------->|
|
||||
// | |
|
||||
// (core) | (attach) (term) (remote) |
|
||||
// .-----------------<-|->------------------. |
|
||||
// | v | |
|
||||
// InferiorUnrunnable | (plain) | |
|
||||
// | | (trk) | |
|
||||
// | | | |
|
||||
// | .--> InferiorRunningRequested | |
|
||||
// | | | | |
|
||||
// | | InferiorRunning | |
|
||||
// | | | | |
|
||||
// | | InferiorStopping | |
|
||||
// | | | | |
|
||||
// | '------ InferiorStopped <-----------' |
|
||||
// | | v
|
||||
// | InferiorShuttingDown -> InferiorShutdownFailed ---->|
|
||||
// | | |
|
||||
// | InferiorShutDown |
|
||||
// | | |
|
||||
// '--------> EngineShuttingDown <--------------------------------'
|
||||
// |
|
||||
// 0
|
||||
//
|
||||
@@ -206,8 +200,7 @@ static const char *stateName(int s)
|
||||
SN(InferiorShuttingDown)
|
||||
SN(InferiorShutDown)
|
||||
SN(InferiorShutdownFailed)
|
||||
SN(AdapterShuttingDown)
|
||||
SN(AdapterShutdownFailed)
|
||||
SN(EngineShuttingDown)
|
||||
}
|
||||
return "<unknown>";
|
||||
#undef SN
|
||||
@@ -290,6 +283,8 @@ struct DebuggerManagerPrivate
|
||||
|
||||
IDebuggerEngine *m_engine;
|
||||
DebuggerState m_state;
|
||||
|
||||
CPlusPlus::Snapshot m_codeModelSnapshot;
|
||||
};
|
||||
|
||||
DebuggerManager *DebuggerManagerPrivate::instance = 0;
|
||||
@@ -610,6 +605,18 @@ WatchHandler *DebuggerManager::watchHandler() const
|
||||
return d->m_watchHandler;
|
||||
}
|
||||
|
||||
const CPlusPlus::Snapshot &DebuggerManager::cppCodeModelSnapshot() const
|
||||
{
|
||||
if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked())
|
||||
d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
|
||||
return d->m_codeModelSnapshot;
|
||||
}
|
||||
|
||||
void DebuggerManager::clearCppCodeModelSnapshot()
|
||||
{
|
||||
d->m_codeModelSnapshot.clear();
|
||||
}
|
||||
|
||||
SourceFilesWindow *DebuggerManager::sourceFileWindow() const
|
||||
{
|
||||
return d->m_sourceFilesWindow;
|
||||
@@ -1013,6 +1020,7 @@ void DebuggerManager::exitDebugger()
|
||||
// in turn will handle the cleanup.
|
||||
if (d->m_engine && state() != DebuggerNotReady)
|
||||
d->m_engine->exitDebugger();
|
||||
d->m_codeModelSnapshot.clear();
|
||||
}
|
||||
|
||||
DebuggerStartParametersPtr DebuggerManager::startParameters() const
|
||||
@@ -1544,7 +1552,7 @@ static bool isAllowedTransition(int from, int to)
|
||||
case AdapterStarting:
|
||||
return to == AdapterStarted || to == AdapterStartFailed;
|
||||
case AdapterStarted:
|
||||
return to == InferiorStarting;
|
||||
return to == InferiorStarting || to == EngineShuttingDown;
|
||||
case AdapterStartFailed:
|
||||
return to == DebuggerNotReady;
|
||||
|
||||
@@ -1552,37 +1560,38 @@ static bool isAllowedTransition(int from, int to)
|
||||
return to == InferiorRunningRequested || to == InferiorStopped
|
||||
|| to == InferiorStartFailed || to == InferiorUnrunnable;
|
||||
case InferiorStartFailed:
|
||||
return to == DebuggerNotReady;
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case InferiorRunningRequested:
|
||||
return to == InferiorRunning;
|
||||
return to == InferiorRunning || to == InferiorStopped;
|
||||
case InferiorRunning:
|
||||
return to == InferiorStopping || to == InferiorShuttingDown;
|
||||
return to == InferiorStopping;
|
||||
|
||||
case InferiorStopping:
|
||||
return to == InferiorStopped || to == InferiorStopFailed;
|
||||
case InferiorStopped:
|
||||
return to == InferiorRunningRequested || to == InferiorShuttingDown;
|
||||
case InferiorStopFailed:
|
||||
return to == DebuggerNotReady;
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case InferiorUnrunnable:
|
||||
return to == AdapterShuttingDown;
|
||||
return to == EngineShuttingDown;
|
||||
case InferiorShuttingDown:
|
||||
return to == InferiorShutDown || to == InferiorShutdownFailed;
|
||||
case InferiorShutDown:
|
||||
return to == AdapterShuttingDown;
|
||||
return to == EngineShuttingDown;
|
||||
case InferiorShutdownFailed:
|
||||
return to == EngineShuttingDown;
|
||||
|
||||
case AdapterShuttingDown:
|
||||
case EngineShuttingDown:
|
||||
return to == DebuggerNotReady;
|
||||
|
||||
default:
|
||||
qDebug() << "UNKNOWN STATE: " << from;
|
||||
}
|
||||
|
||||
qDebug() << "UNKNOWN STATE:" << from;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebuggerManager::setState(DebuggerState state)
|
||||
void DebuggerManager::setState(DebuggerState state, bool forced)
|
||||
{
|
||||
//STATE_DEBUG("STATUS CHANGE: FROM " << stateName(d->m_state)
|
||||
// << " TO " << stateName(state));
|
||||
@@ -1591,7 +1600,7 @@ void DebuggerManager::setState(DebuggerState state)
|
||||
.arg(stateName(d->m_state)).arg(d->m_state).arg(stateName(state)).arg(state);
|
||||
//if (!((d->m_state == -1 && state == 0) || (d->m_state == 0 && state == 0)))
|
||||
// qDebug() << msg;
|
||||
if (!isAllowedTransition(d->m_state, state))
|
||||
if (!forced && !isAllowedTransition(d->m_state, state))
|
||||
qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
|
||||
|
||||
showDebuggerOutput(LogDebug, msg);
|
||||
@@ -1685,8 +1694,7 @@ bool DebuggerManager::debuggerActionsEnabled() const
|
||||
case InferiorShuttingDown:
|
||||
case InferiorShutDown:
|
||||
case InferiorShutdownFailed:
|
||||
case AdapterShuttingDown:
|
||||
case AdapterShutdownFailed:
|
||||
case EngineShuttingDown:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
@@ -1763,9 +1771,9 @@ DebuggerState IDebuggerEngine::state() const
|
||||
return m_manager->state();
|
||||
}
|
||||
|
||||
void IDebuggerEngine::setState(DebuggerState state)
|
||||
void IDebuggerEngine::setState(DebuggerState state, bool forced)
|
||||
{
|
||||
m_manager->setState(state);
|
||||
m_manager->setState(state, forced);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@@ -59,6 +59,10 @@ namespace TextEditor {
|
||||
class ITextEditor;
|
||||
}
|
||||
|
||||
namespace CPlusPlus {
|
||||
class Snapshot;
|
||||
}
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -183,6 +187,8 @@ public:
|
||||
QString *settingsCategory = 0,
|
||||
QString *settingsPage = 0) const;
|
||||
|
||||
const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
|
||||
|
||||
static DebuggerManager *instance();
|
||||
|
||||
public slots:
|
||||
@@ -235,6 +241,7 @@ public slots:
|
||||
void setRegisterValue(int nr, const QString &value);
|
||||
|
||||
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
|
||||
void clearCppCodeModelSnapshot();
|
||||
|
||||
public slots: // FIXME
|
||||
void showDebuggerOutput(const QString &msg)
|
||||
@@ -270,7 +277,8 @@ private:
|
||||
Internal::ThreadsHandler *threadsHandler() const;
|
||||
Internal::WatchHandler *watchHandler() const;
|
||||
Internal::SourceFilesWindow *sourceFileWindow() const;
|
||||
QWidget *threadsWindow() const;
|
||||
QWidget *threadsWindow() const;
|
||||
|
||||
Internal::DebuggerManagerActions debuggerManagerActions() const;
|
||||
|
||||
void notifyInferiorStopped();
|
||||
@@ -280,7 +288,7 @@ private:
|
||||
|
||||
void cleanupViews();
|
||||
|
||||
void setState(DebuggerState state);
|
||||
void setState(DebuggerState state, bool forced = false);
|
||||
|
||||
//
|
||||
// internal implementation
|
||||
|
@@ -373,6 +373,9 @@ QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
|
||||
m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
|
||||
m_ui.dumperLocationChooser);
|
||||
|
||||
m_group.insert(theDebuggerAction(UseCodeModel),
|
||||
m_ui.checkBoxUseCodeModel);
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
|
||||
m_ui.checkBoxDebugDebuggingHelpers);
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>403</width>
|
||||
<width>432</width>
|
||||
<height>434</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -83,10 +83,20 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Utils::PathChooser" name="dumperLocationChooser" native="true"/>
|
||||
<widget class="Utils::PathChooser" name="dumperLocationChooser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxUseCodeModel">
|
||||
<property name="toolTip">
|
||||
<string>Makes use of Qt Creator's code model to find out if a variable has already been assigned a value at the point the debugger interrupts.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use code model</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxDebugDebuggingHelpers">
|
||||
<property name="toolTip">
|
||||
|
@@ -31,7 +31,6 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
namespace Debugger {
|
||||
@@ -47,35 +46,22 @@ AbstractGdbAdapter::~AbstractGdbAdapter()
|
||||
disconnect();
|
||||
}
|
||||
|
||||
// This cannot be in the c'tor, as it would not connect the "virtual" slots
|
||||
void AbstractGdbAdapter::commonInit()
|
||||
void AbstractGdbAdapter::shutdown()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(handleGdbError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(started()),
|
||||
this, SLOT(handleGdbStarted()));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
this, SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
this, SIGNAL(readyReadStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
this, SIGNAL(readyReadStandardError()));
|
||||
}
|
||||
|
||||
QByteArray AbstractGdbAdapter::readAllStandardOutput()
|
||||
void AbstractGdbAdapter::startInferiorPhase2()
|
||||
{
|
||||
return m_gdbProc.readAllStandardOutput();
|
||||
}
|
||||
|
||||
QByteArray AbstractGdbAdapter::readAllStandardError()
|
||||
const char *AbstractGdbAdapter::inferiorShutdownCommand() const
|
||||
{
|
||||
return m_gdbProc.readAllStandardError();
|
||||
return "kill";
|
||||
}
|
||||
|
||||
void AbstractGdbAdapter::write(const QByteArray &data)
|
||||
{
|
||||
m_gdbProc.write(data);
|
||||
m_engine->m_gdbProc.write(data);
|
||||
}
|
||||
|
||||
bool AbstractGdbAdapter::isTrkAdapter() const
|
||||
|
@@ -42,7 +42,7 @@ namespace Internal {
|
||||
// debugging and TrkGdbAdapter used for on-device debugging.
|
||||
// In the PlainGdbAdapter case it's just a wrapper around a QProcess running
|
||||
// gdb, in the TrkGdbAdapter case it's the interface to the gdb process in
|
||||
// the whole rfomm/gdb/gdbserver combo.
|
||||
// the whole rfcomm/gdb/gdbserver combo.
|
||||
class AbstractGdbAdapter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -51,34 +51,44 @@ public:
|
||||
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||
virtual ~AbstractGdbAdapter();
|
||||
|
||||
QByteArray readAllStandardOutput();
|
||||
QByteArray readAllStandardError();
|
||||
virtual void write(const QByteArray &data);
|
||||
virtual bool isTrkAdapter() const; // isUtterlyBrokenAdapter
|
||||
|
||||
virtual void startAdapter() = 0;
|
||||
virtual void startInferior() = 0;
|
||||
virtual void startInferiorPhase2();
|
||||
virtual void interruptInferior() = 0;
|
||||
virtual void shutdown() = 0;
|
||||
virtual void shutdown();
|
||||
virtual const char *inferiorShutdownCommand() const;
|
||||
|
||||
virtual bool dumpersAvailable() const = 0;
|
||||
|
||||
static QString msgGdbStopFailed(const QString &why);
|
||||
static QString msgInferiorStopFailed(const QString &why);
|
||||
static QString msgAttachedToStoppedInferior();
|
||||
static QString msgInferiorStarted();
|
||||
static QString msgInferiorRunning();
|
||||
static QString msgConnectRemoteServerFailed(const QString &why);
|
||||
|
||||
signals:
|
||||
void adapterStarted();
|
||||
|
||||
// Something went wrong with the adapter *before* adapterStarted() was emitted.
|
||||
// Make sure to clean up everything before emitting this signal.
|
||||
void adapterStartFailed(const QString &msg, const QString &settingsIdHint);
|
||||
void adapterShutDown();
|
||||
void adapterShutdownFailed(const QString &msg);
|
||||
|
||||
// Something went wrong with the adapter *after* adapterStarted() was emitted.
|
||||
// Make sure to clean up everything before emitting this signal.
|
||||
void adapterCrashed(const QString &msg);
|
||||
|
||||
void inferiorStartFailed(const QString &msg);
|
||||
void inferiorShutDown();
|
||||
void inferiorShutdownFailed(const QString &msg);
|
||||
|
||||
void readyReadStandardOutput();
|
||||
void readyReadStandardError();
|
||||
// This triggers the initial breakpoint synchronization and causes
|
||||
// startInferiorPhase2() being called once done.
|
||||
void inferiorPrepared();
|
||||
|
||||
// The adapter is still running just fine, but it failed to acquire a debuggee.
|
||||
void inferiorStartFailed(const QString &msg);
|
||||
|
||||
protected:
|
||||
void commonInit();
|
||||
DebuggerState state() const
|
||||
{ return m_engine->state(); }
|
||||
void setState(DebuggerState state)
|
||||
@@ -89,17 +99,10 @@ protected:
|
||||
{ m_engine->debugMessage(msg); }
|
||||
void showStatusMessage(const QString &msg) const
|
||||
{ m_engine->showStatusMessage(msg); }
|
||||
|
||||
static QString msgGdbStopFailed(const QString &why);
|
||||
static QString msgInferiorStopFailed(const QString &why);
|
||||
static QString msgAttachedToStoppedInferior();
|
||||
static QString msgInferiorStarted();
|
||||
static QString msgInferiorRunning();
|
||||
static QString msgConnectRemoteServerFailed(const QString &why);
|
||||
void showMessageBox(int icon, const QString &title, const QString &text) const
|
||||
{ m_engine->showMessageBox(icon, title, text); }
|
||||
|
||||
GdbEngine * const m_engine;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -29,7 +29,6 @@
|
||||
|
||||
#include "attachgdbadapter.h"
|
||||
|
||||
#include "debuggeractions.h"
|
||||
#include "gdbengine.h"
|
||||
#include "procinterrupt.h"
|
||||
#include "debuggerstringutils.h"
|
||||
@@ -53,7 +52,6 @@ namespace Internal {
|
||||
AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::startAdapter()
|
||||
@@ -62,28 +60,12 @@ void AttachGdbAdapter::startAdapter()
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
if (!m_engine->startGdb())
|
||||
return;
|
||||
|
||||
QString location = theDebuggerStringSetting(GdbLocation);
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
setState(AdapterStarted);
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
@@ -99,6 +81,7 @@ void AttachGdbAdapter::handleAttach(const GdbResponse &response)
|
||||
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
|
||||
debugMessage(_("INFERIOR ATTACHED"));
|
||||
showStatusMessage(msgAttachedToStoppedInferior());
|
||||
emit inferiorPrepared();
|
||||
m_engine->updateAll();
|
||||
} else {
|
||||
QString msg = __(response.data.findChild("msg").data());
|
||||
@@ -114,59 +97,5 @@ void AttachGdbAdapter::interruptInferior()
|
||||
debugMessage(_("CANNOT INTERRUPT %1").arg(pid));
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
|
||||
case InferiorStartFailed:
|
||||
m_engine->postCommand(_("-gdb-exit"));
|
||||
setState(DebuggerNotReady);
|
||||
return;
|
||||
|
||||
case InferiorStopped:
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("detach"), CB(handleDetach));
|
||||
return;
|
||||
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleDetach(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROESS FINISHED"));
|
||||
setState(DebuggerNotReady);
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
@@ -31,10 +31,6 @@
|
||||
#define DEBUGGER_ATTACHGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -57,16 +53,10 @@ public:
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
const char *inferiorShutdownCommand() const { return "detach"; }
|
||||
|
||||
private:
|
||||
void handleAttach(const GdbResponse &response);
|
||||
void handleDetach(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -35,7 +35,9 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -53,7 +55,6 @@ namespace Internal {
|
||||
CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::startAdapter()
|
||||
@@ -62,85 +63,42 @@ void CoreGdbAdapter::startAdapter()
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
if (!m_engine->startGdb())
|
||||
return;
|
||||
|
||||
QString location = theDebuggerStringSetting(GdbLocation);
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
setState(AdapterStarted);
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
QFileInfo fi(startParameters().coreFile);
|
||||
m_executable = startParameters().executable;
|
||||
if (m_executable.isEmpty()) {
|
||||
#ifdef EXE_FROM_CORE
|
||||
// Extra round trip to get executable name from core file.
|
||||
// This is sometimes not the full name, so it can't be used
|
||||
// as the generic solution.
|
||||
// Quoting core name below fails in gdb 6.8-debian.
|
||||
QString coreName = fi.absoluteFilePath();
|
||||
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore1));
|
||||
} else {
|
||||
// Directly load symbols.
|
||||
QFileInfo fi(m_executable);
|
||||
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
|
||||
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
|
||||
|
||||
m_round = 1;
|
||||
loadCoreFile();
|
||||
#else
|
||||
showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"),
|
||||
tr("No executable to load symbols from specified."));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#ifdef EXE_FROM_CORE
|
||||
m_round = 2;
|
||||
#endif
|
||||
loadExeAndSyms();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleTargetCore1(const GdbResponse &response)
|
||||
void CoreGdbAdapter::loadExeAndSyms()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
showStatusMessage(tr("Attached to core temporarily."));
|
||||
GdbMi console = response.data.findChild("consolestreamoutput");
|
||||
int pos1 = console.data().indexOf('`');
|
||||
int pos2 = console.data().indexOf('\'');
|
||||
if (pos1 == -1 || pos2 == -1) {
|
||||
emit inferiorStartFailed(tr("No binary found."));
|
||||
} else {
|
||||
m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1);
|
||||
// Strip off command line arguments. FIXME: make robust.
|
||||
if (m_executable.contains(' '))
|
||||
m_executable = m_executable.section(' ', 0, 0);
|
||||
QTC_ASSERT(!m_executable.isEmpty(), /**/);
|
||||
// Finish extra round.
|
||||
m_engine->postCommand(_("detach"), CB(handleDetach1));
|
||||
}
|
||||
} else {
|
||||
const QByteArray msg = response.data.findChild("msg").data();
|
||||
emit inferiorStartFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleDetach1(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// Load symbols.
|
||||
QFileInfo fi(m_executable);
|
||||
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
|
||||
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
|
||||
} else {
|
||||
const QByteArray msg = response.data.findChild("msg").data();
|
||||
emit inferiorStartFailed(msg);
|
||||
}
|
||||
// Do that first, otherwise no symbols are loaded.
|
||||
QFileInfo fi(m_executable);
|
||||
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
|
||||
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
@@ -148,74 +106,70 @@ void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
showStatusMessage(tr("Symbols found."));
|
||||
// Quoting core name below fails in gdb 6.8-debian.
|
||||
QFileInfo fi(startParameters().coreFile);
|
||||
QString coreName = fi.absoluteFilePath();
|
||||
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore2));
|
||||
} else {
|
||||
QString msg = tr("Symbols not found in \"%1\" failed:\n%2")
|
||||
.arg(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorUnrunnable);
|
||||
m_engine->updateAll();
|
||||
// emit inferiorStartFailed(msg);
|
||||
QString msg = tr("Loading symbols from \"%1\" failed:\n").arg(m_executable)
|
||||
+ __(response.data.findChild("msg").data());
|
||||
showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), msg);
|
||||
}
|
||||
loadCoreFile();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleTargetCore2(const GdbResponse &response)
|
||||
void CoreGdbAdapter::loadCoreFile()
|
||||
{
|
||||
// Quoting core name below fails in gdb 6.8-debian.
|
||||
QFileInfo fi(startParameters().coreFile);
|
||||
QString coreName = fi.absoluteFilePath();
|
||||
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore));
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
#ifdef EXE_FROM_CORE
|
||||
if (m_round == 1) {
|
||||
m_round = 2;
|
||||
GdbMi console = response.data.findChild("consolestreamoutput");
|
||||
int pos1 = console.data().indexOf('`');
|
||||
int pos2 = console.data().indexOf('\'');
|
||||
if (pos1 != -1 && pos2 != -1) {
|
||||
m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1);
|
||||
// Strip off command line arguments. FIXME: make robust.
|
||||
int idx = m_executable.indexOf(_c(' '));
|
||||
if (idx >= 0)
|
||||
m_executable.truncate(idx);
|
||||
if (!m_executable.isEmpty()) {
|
||||
m_executable = QFileInfo(startParameters().coreFile).absoluteDir()
|
||||
.absoluteFilePath(m_executable);
|
||||
if (QFile::exists(m_executable)) {
|
||||
// Finish extra round ...
|
||||
showStatusMessage(tr("Attached to core temporarily."));
|
||||
m_engine->postCommand(_("detach"));
|
||||
// ... and retry.
|
||||
loadExeAndSyms();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"),
|
||||
tr("Unable to determine executable from core file."));
|
||||
}
|
||||
#endif
|
||||
showStatusMessage(tr("Attached to core."));
|
||||
setState(InferiorUnrunnable);
|
||||
m_engine->updateAll();
|
||||
} else {
|
||||
QString msg = tr("Attach to core \"%1\" failed:\n%2")
|
||||
.arg(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorUnrunnable);
|
||||
m_engine->updateAll();
|
||||
// emit inferiorStartFailed(msg);
|
||||
QString msg = tr("Attach to core \"%1\" failed:\n").arg(startParameters().coreFile)
|
||||
+ __(response.data.findChild("msg").data());
|
||||
emit inferiorStartFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::interruptInferior()
|
||||
{
|
||||
// A core should never 'run'
|
||||
QTC_ASSERT(false, /**/);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
|
||||
case DebuggerNotReady:
|
||||
return;
|
||||
|
||||
case InferiorUnrunnable:
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROESS FINISHED"));
|
||||
setState(DebuggerNotReady);
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
@@ -31,10 +31,10 @@
|
||||
#define DEBUGGER_COREGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QProcess>
|
||||
#ifdef Q_OS_LINUX
|
||||
# define EXE_FROM_CORE
|
||||
#endif
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -57,19 +57,16 @@ public:
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
void handleTargetCore1(const GdbResponse &response);
|
||||
void handleDetach1(const GdbResponse &response);
|
||||
void loadExeAndSyms();
|
||||
void loadCoreFile();
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleTargetCore2(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
|
||||
void handleTargetCore(const GdbResponse &response);
|
||||
|
||||
#ifdef EXE_FROM_CORE
|
||||
int m_round;
|
||||
#endif
|
||||
QString m_executable;
|
||||
};
|
||||
|
||||
|
@@ -16,6 +16,7 @@ HEADERS += \
|
||||
$$PWD/attachgdbadapter.h \
|
||||
$$PWD/coregdbadapter.h \
|
||||
$$PWD/plaingdbadapter.h \
|
||||
$$PWD/termgdbadapter.h \
|
||||
$$PWD/remotegdbadapter.h \
|
||||
$$PWD/trkgdbadapter.h \
|
||||
|
||||
@@ -30,6 +31,7 @@ SOURCES += \
|
||||
$$PWD/attachgdbadapter.cpp \
|
||||
$$PWD/coregdbadapter.cpp \
|
||||
$$PWD/plaingdbadapter.cpp \
|
||||
$$PWD/termgdbadapter.cpp \
|
||||
$$PWD/remotegdbadapter.cpp \
|
||||
$$PWD/trkgdbadapter.cpp \
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include "attachgdbadapter.h"
|
||||
#include "coregdbadapter.h"
|
||||
#include "plaingdbadapter.h"
|
||||
#include "termgdbadapter.h"
|
||||
#include "remotegdbadapter.h"
|
||||
#include "trkgdbadapter.h"
|
||||
|
||||
@@ -89,10 +90,6 @@
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
// FIXME: temporary hack to evalaute tbreak based step-over behaviour
|
||||
static QString lastFile;
|
||||
static int lastLine;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -109,17 +106,29 @@ namespace Internal {
|
||||
|
||||
static bool stateAcceptsGdbCommands(DebuggerState state)
|
||||
{
|
||||
return state == AdapterStarted
|
||||
|| state == InferiorUnrunnable
|
||||
|| state == InferiorStarting
|
||||
|| state == InferiorRunningRequested
|
||||
|| state == InferiorRunning
|
||||
|| state == InferiorStopping
|
||||
|| state == InferiorStopped
|
||||
|| state == InferiorShuttingDown
|
||||
|| state == InferiorShutDown
|
||||
|| state == AdapterShuttingDown;
|
||||
};
|
||||
switch (state) {
|
||||
case AdapterStarting:
|
||||
case AdapterStarted:
|
||||
case AdapterStartFailed:
|
||||
case InferiorUnrunnable:
|
||||
case InferiorStarting:
|
||||
case InferiorStartFailed:
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopped:
|
||||
case InferiorShuttingDown:
|
||||
case InferiorShutDown:
|
||||
case InferiorShutdownFailed:
|
||||
return true;
|
||||
case DebuggerNotReady:
|
||||
case EngineStarting:
|
||||
case InferiorStopFailed:
|
||||
case EngineShuttingDown:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ¤tToken()
|
||||
{
|
||||
@@ -221,27 +230,16 @@ GdbEngine::~GdbEngine()
|
||||
|
||||
void GdbEngine::connectAdapter()
|
||||
{
|
||||
// Gdb Process interaction
|
||||
connect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readGdbStandardOutput()));
|
||||
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readGdbStandardError()));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(adapterStarted()),
|
||||
this, SLOT(handleAdapterStarted()));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
|
||||
this, SLOT(handleAdapterStartFailed(QString,QString)));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterShutDown()),
|
||||
this, SLOT(handleAdapterShutDown()));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
|
||||
this, SLOT(handleAdapterShutdownFailed(QString)));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
|
||||
this, SLOT(handleInferiorPrepared()));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
|
||||
this, SLOT(handleInferiorStartFailed(QString)));
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorShutDown()),
|
||||
this, SLOT(handleInferiorShutDown()));
|
||||
connect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
|
||||
this, SLOT(handleInferiorShutdownFailed(QString)));
|
||||
|
||||
connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)),
|
||||
this, SLOT(handleAdapterCrashed(QString)));
|
||||
@@ -265,7 +263,6 @@ void GdbEngine::initializeVariables()
|
||||
m_commandsDoneCallback = 0;
|
||||
m_commandsToRunOnTemporaryBreak.clear();
|
||||
m_cookieForToken.clear();
|
||||
m_customOutputForToken.clear();
|
||||
|
||||
m_pendingConsoleStreamOutput.clear();
|
||||
m_pendingLogStreamOutput.clear();
|
||||
@@ -561,11 +558,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
m_pendingLogStreamOutput);
|
||||
response.data.setStreamOutput("consolestreamoutput",
|
||||
m_pendingConsoleStreamOutput);
|
||||
QByteArray custom = m_customOutputForToken[token];
|
||||
if (!custom.isEmpty())
|
||||
response.data.setStreamOutput("customvaluecontents",
|
||||
'{' + custom + '}');
|
||||
//m_customOutputForToken.remove(token);
|
||||
m_pendingLogStreamOutput.clear();
|
||||
m_pendingConsoleStreamOutput.clear();
|
||||
|
||||
@@ -581,7 +573,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
|
||||
void GdbEngine::readGdbStandardError()
|
||||
{
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError();
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
|
||||
}
|
||||
|
||||
void GdbEngine::readGdbStandardOutput()
|
||||
@@ -589,7 +581,7 @@ void GdbEngine::readGdbStandardOutput()
|
||||
int newstart = 0;
|
||||
int scan = m_inbuffer.size();
|
||||
|
||||
m_inbuffer.append(m_gdbAdapter->readAllStandardOutput());
|
||||
m_inbuffer.append(m_gdbProc.readAllStandardOutput());
|
||||
|
||||
while (newstart < m_inbuffer.size()) {
|
||||
int start = newstart;
|
||||
@@ -704,13 +696,13 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
|
||||
}
|
||||
|
||||
if (cmd.flags & NeedsStop) {
|
||||
if (state() == InferiorStopped || state() == AdapterStarted) {
|
||||
if (state() == InferiorStopped
|
||||
|| state() == InferiorStarting || state() == AdapterStarted) {
|
||||
// Can be safely sent now.
|
||||
flushCommand(cmd);
|
||||
} else {
|
||||
// Queue the commands that we cannot send at once.
|
||||
showStatusMessage(tr("Stopping temporarily."), 1000);
|
||||
qDebug() << _("QUEUING COMMAND ") + cmd.command;
|
||||
debugMessage(_("QUEUING COMMAND ") + cmd.command);
|
||||
m_commandsToRunOnTemporaryBreak.append(cmd);
|
||||
interruptInferior();
|
||||
@@ -896,14 +888,6 @@ void GdbEngine::handleQuerySources(const GdbResponse &response)
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::handleInfoShared(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// let the modules handler do the parsing
|
||||
handleModulesList(response);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void GdbEngine::handleExecJumpToLine(const GdbResponse &response)
|
||||
{
|
||||
@@ -1078,7 +1062,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern);
|
||||
debugMessage(_("PATTERN: ") + pat);
|
||||
postCommand(_("sharedlibrary ") + pat);
|
||||
continueInferior();
|
||||
continueInferiorInternal();
|
||||
showStatusMessage(tr("Loading %1...").arg(dataStr));
|
||||
return;
|
||||
}
|
||||
@@ -1093,7 +1077,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
||||
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
|
||||
//if (reason == "signal-received"
|
||||
// && data.findChild("signal-name").data() == "SIGTRAP") {
|
||||
// continueInferior();
|
||||
// continueInferiorInternal();
|
||||
// return;
|
||||
//}
|
||||
|
||||
@@ -1194,7 +1178,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
||||
reloadSourceFiles();
|
||||
postCommand(_("-break-list"), CB(handleBreakList));
|
||||
QVariant var = QVariant::fromValue<GdbMi>(data);
|
||||
postCommand(_("p 0"), CB(handleStop2), var); // dummy
|
||||
postCommand(_("p 2"), CB(handleStop2), var); // dummy
|
||||
} else {
|
||||
#ifdef Q_OS_LINUX
|
||||
// For some reason, attaching to a stopped process causes *two* stops
|
||||
@@ -1205,8 +1189,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
||||
GdbMi frameData = data.findChild("frame");
|
||||
if (frameData.findChild("func").data() == "_start"
|
||||
&& frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
|
||||
setState(InferiorRunningRequested);
|
||||
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
|
||||
continueInferiorInternal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1247,9 +1230,9 @@ void GdbEngine::handleStop2(const GdbResponse &response)
|
||||
void GdbEngine::handleStop2(const GdbMi &data)
|
||||
{
|
||||
// Sometimes we get some interesting extra information. Grab it.
|
||||
GdbMi frame = data.findChild("frame");
|
||||
GdbMi shortName = frame.findChild("file");
|
||||
GdbMi fullName = frame.findChild("fullname");
|
||||
const GdbMi gdbmiFrame = data.findChild("frame");
|
||||
GdbMi shortName = gdbmiFrame.findChild("file");
|
||||
GdbMi fullName = gdbmiFrame.findChild("fullname");
|
||||
if (shortName.isValid() && fullName.isValid()) {
|
||||
QString file = QFile::decodeName(shortName.data());
|
||||
QString full = QFile::decodeName(fullName.data());
|
||||
@@ -1260,16 +1243,17 @@ void GdbEngine::handleStop2(const GdbMi &data)
|
||||
}
|
||||
|
||||
// Quick shot: Jump to stack frame #0.
|
||||
if (frame.isValid()) {
|
||||
const StackFrame f = parseStackFrame(frame, 0);
|
||||
gotoLocation(f, true);
|
||||
StackFrame frame;
|
||||
if (gdbmiFrame.isValid()) {
|
||||
frame = parseStackFrame(gdbmiFrame, 0);
|
||||
gotoLocation(frame, true);
|
||||
}
|
||||
|
||||
//
|
||||
// Stack
|
||||
//
|
||||
manager()->stackHandler()->setCurrentIndex(0);
|
||||
updateLocals(); // Quick shot
|
||||
updateLocals(qVariantFromValue(frame)); // Quick shot
|
||||
|
||||
reloadStack(false);
|
||||
|
||||
@@ -1342,17 +1326,16 @@ void GdbEngine::handleExecContinue(const GdbResponse &response)
|
||||
QTC_ASSERT(state() == InferiorRunning, /**/);
|
||||
} else {
|
||||
QTC_ASSERT(state() == InferiorRunningRequested, /**/);
|
||||
setState(InferiorStopped);
|
||||
QByteArray msg = response.data.findChild("msg").data();
|
||||
if (msg.startsWith("Cannot find bounds of current function")) {
|
||||
setState(InferiorStopped);
|
||||
showStatusMessage(tr("Stopped."), 5000);
|
||||
//showStatusMessage(tr("No debug information available. "
|
||||
// "Leaving function..."));
|
||||
//stepOutExec();
|
||||
} else {
|
||||
showMessageBox(QMessageBox::Critical, tr("Error"),
|
||||
tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg));
|
||||
QTC_ASSERT(state() == InferiorRunning, /**/);
|
||||
showMessageBox(QMessageBox::Critical, tr("Execution Error"),
|
||||
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
@@ -1397,8 +1380,73 @@ QString GdbEngine::fullName(const QStringList &candidates)
|
||||
void GdbEngine::shutdown()
|
||||
{
|
||||
debugMessage(_("INITIATE GDBENGINE SHUTDOWN"));
|
||||
initializeVariables();
|
||||
m_gdbAdapter->shutdown();
|
||||
switch (state()) {
|
||||
case DebuggerNotReady: // Nothing to do! :)
|
||||
case EngineStarting: // We can't get here, really
|
||||
case InferiorShuttingDown: // Will auto-trigger further shutdown steps
|
||||
case EngineShuttingDown: // Do not disturb! :)
|
||||
break;
|
||||
case AdapterStarting: // GDB is up, adapter is "doing something"
|
||||
setState(AdapterStartFailed);
|
||||
m_gdbAdapter->shutdown();
|
||||
// fall-through
|
||||
case AdapterStartFailed: // Adapter "did something", but it did not help
|
||||
// FIXME set some timeout?
|
||||
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
|
||||
break;
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopped:
|
||||
// FIXME set some timeout?
|
||||
postCommand(_(m_gdbAdapter->inferiorShutdownCommand()),
|
||||
NeedsStop, CB(handleInferiorShutdown));
|
||||
setState(InferiorShuttingDown); // Do it after posting the command!
|
||||
break;
|
||||
case AdapterStarted: // We can't get here, really
|
||||
case InferiorStartFailed:
|
||||
case InferiorShutDown:
|
||||
case InferiorShutdownFailed: // Whatever
|
||||
case InferiorUnrunnable:
|
||||
// FIXME set some timeout?
|
||||
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
|
||||
setState(EngineShuttingDown); // Do it after posting the command!
|
||||
break;
|
||||
case InferiorStarting: // This may take some time, so just short-circuit it
|
||||
setState(InferiorStartFailed);
|
||||
// fall-through
|
||||
case InferiorStopFailed: // Tough luck, I guess. But unreachable as of now anyway.
|
||||
setState(EngineShuttingDown);
|
||||
m_gdbProc.terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorShutdown(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
|
||||
setState(InferiorShutDown);
|
||||
} else {
|
||||
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
|
||||
setState(InferiorShutdownFailed);
|
||||
QString msg = m_gdbAdapter->msgInferiorStopFailed(_(response.data.findChild("msg").data()));
|
||||
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
|
||||
}
|
||||
shutdown(); // re-iterate...
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultExit) {
|
||||
debugMessage(_("GDB CLAIMS EXIT; WAITING"));
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
QString msg = m_gdbAdapter->msgGdbStopFailed(_(response.data.findChild("msg").data()));
|
||||
debugMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
|
||||
m_gdbProc.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::detachDebugger()
|
||||
@@ -1414,8 +1462,7 @@ void GdbEngine::detachDebugger()
|
||||
void GdbEngine::exitDebugger() // called from the manager
|
||||
{
|
||||
disconnectDebuggingHelperActions();
|
||||
initializeVariables();
|
||||
m_gdbAdapter->shutdown();
|
||||
shutdown();
|
||||
}
|
||||
|
||||
int GdbEngine::currentFrame() const
|
||||
@@ -1463,6 +1510,8 @@ AbstractGdbAdapter *GdbEngine::createAdapter(const DebuggerStartParametersPtr &s
|
||||
case AttachExternal:
|
||||
return new AttachGdbAdapter(this);
|
||||
default:
|
||||
if (sp->useTerminal)
|
||||
return new TermGdbAdapter(this);
|
||||
return new PlainGdbAdapter(this);
|
||||
}
|
||||
}
|
||||
@@ -1476,25 +1525,23 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
||||
// initializeVariables());
|
||||
//QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0);
|
||||
|
||||
initializeVariables();
|
||||
|
||||
m_startParameters = sp;
|
||||
|
||||
delete m_gdbAdapter;
|
||||
m_gdbAdapter = createAdapter(sp);
|
||||
connectAdapter();
|
||||
|
||||
if (startModeAllowsDumpers())
|
||||
connectDebuggingHelperActions();
|
||||
|
||||
initializeVariables();
|
||||
connectAdapter();
|
||||
|
||||
m_gdbAdapter->startAdapter();
|
||||
}
|
||||
|
||||
void GdbEngine::continueInferiorInternal()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
|
||||
m_manager->resetLocation();
|
||||
setTokenBarrier();
|
||||
setState(InferiorRunningRequested);
|
||||
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
|
||||
}
|
||||
@@ -1507,6 +1554,8 @@ void GdbEngine::autoContinueInferior()
|
||||
|
||||
void GdbEngine::continueInferior()
|
||||
{
|
||||
m_manager->resetLocation();
|
||||
setTokenBarrier();
|
||||
continueInferiorInternal();
|
||||
showStatusMessage(tr("Running requested..."), 5000);
|
||||
}
|
||||
@@ -1589,12 +1638,10 @@ void GdbEngine::runToFunctionExec(const QString &functionName)
|
||||
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
|
||||
setTokenBarrier();
|
||||
postCommand(_("-break-insert -t ") + functionName);
|
||||
setState(InferiorRunningRequested);
|
||||
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
|
||||
// that should be "^running". We need to handle the resulting
|
||||
// "Stopped"
|
||||
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
|
||||
continueInferiorInternal();
|
||||
//setState(InferiorRunningRequested);
|
||||
//postCommand(_("-exec-continue"), handleExecRunToFunction);
|
||||
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
|
||||
}
|
||||
|
||||
void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
|
||||
@@ -1903,11 +1950,7 @@ void GdbEngine::handleBreakInsert(const GdbResponse &response)
|
||||
const BreakpointData *data = handler->at(index);
|
||||
// Note that it is perfectly correct that the file name is put
|
||||
// in quotes but not escaped. GDB simply is like that.
|
||||
#if defined(Q_OS_WIN)
|
||||
QFileInfo fi(data->fileName);
|
||||
QString where = _c('"') + fi.fileName() + _("\":")
|
||||
+ data->lineNumber;
|
||||
#elif defined(Q_OS_MAC)
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
QFileInfo fi(data->fileName);
|
||||
QString where = _c('"') + fi.fileName() + _("\":")
|
||||
+ data->lineNumber;
|
||||
@@ -2597,11 +2640,6 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos,
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//: Variable
|
||||
static const QString strNotInScope =
|
||||
QCoreApplication::translate("Debugger::Internal::GdbEngine", "<not in scope>");
|
||||
|
||||
|
||||
static void setWatchDataValue(WatchData &data, const GdbMi &mi,
|
||||
int encoding = 0)
|
||||
{
|
||||
@@ -2818,8 +2856,8 @@ void GdbEngine::updateSubItem(const WatchData &data0)
|
||||
qDebug() << "FIXME: GdbEngine::updateSubItem:"
|
||||
<< data.toString() << "should not happen";
|
||||
#else
|
||||
data.setType(strNotInScope);
|
||||
data.setValue(strNotInScope);
|
||||
data.setType(WatchData::msgNotInScope());
|
||||
data.setValue(WatchData::msgNotInScope());
|
||||
data.setHasChildren(false);
|
||||
insertData(data);
|
||||
return;
|
||||
@@ -2964,7 +3002,7 @@ void GdbEngine::updateWatchData(const WatchData &data)
|
||||
if (isSynchroneous()) {
|
||||
// This should only be called for fresh expanded items, not for
|
||||
// items that had their children retrieved earlier.
|
||||
qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
|
||||
//qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
|
||||
#if 0
|
||||
WatchData data1 = data;
|
||||
data1.setAllUnneeded();
|
||||
@@ -3153,7 +3191,7 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
|
||||
} else {
|
||||
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||
if (data.isWatcher()) {
|
||||
data.value = strNotInScope;
|
||||
data.value = WatchData::msgNotInScope();
|
||||
data.type = _(" ");
|
||||
data.setAllUnneeded();
|
||||
data.setHasChildren(false);
|
||||
@@ -3206,7 +3244,7 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResponse &response)
|
||||
&& msg.startsWith(__("The program being debugged stopped while"))
|
||||
&& msg.contains(__("qDumpObjectData440"))) {
|
||||
// Fake full stop
|
||||
postCommand(_("p 0"), CB(handleStop2)); // dummy
|
||||
postCommand(_("p 3"), CB(handleStop2)); // dummy
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -3227,7 +3265,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResponse &response)
|
||||
|
||||
GdbMi contents;
|
||||
if (!parseConsoleStream(response, &contents)) {
|
||||
data.setError(strNotInScope);
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
insertData(data);
|
||||
return;
|
||||
}
|
||||
@@ -3320,7 +3358,7 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
|
||||
// << " STREAM:" << out;
|
||||
if (list.isEmpty()) {
|
||||
//: Value for variable
|
||||
data.setError(strNotInScope);
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
data.setAllUnneeded();
|
||||
insertData(data);
|
||||
} else if (data.type == __("QString")
|
||||
@@ -3365,19 +3403,19 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
|
||||
}
|
||||
} else {
|
||||
//: Value for variable
|
||||
data.setError(strNotInScope);
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
data.setAllUnneeded();
|
||||
insertData(data);
|
||||
}
|
||||
} else {
|
||||
WatchData data = response.cookie.value<WatchData>();
|
||||
data.setError(strNotInScope);
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
data.setAllUnneeded();
|
||||
insertData(data);
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::updateLocals()
|
||||
void GdbEngine::updateLocals(const QVariant &cookie)
|
||||
{
|
||||
m_pendingRequests = 0;
|
||||
m_processedNames.clear();
|
||||
@@ -3398,8 +3436,8 @@ void GdbEngine::updateLocals()
|
||||
postCommand(_("bb %1 %2")
|
||||
.arg(int(theDebuggerBoolSetting(UseDebuggingHelpers)))
|
||||
.arg(expanded.join(_(","))),
|
||||
WatchUpdate, CB(handleStackFrame1));
|
||||
postCommand(_("p 0"), WatchUpdate, CB(handleStackFrame2));
|
||||
CB(handleStackFrame1));
|
||||
postCommand(_("p 1"), CB(handleStackFrame2));
|
||||
} else {
|
||||
QString level = QString::number(currentFrame());
|
||||
// '2' is 'list with type and value'
|
||||
@@ -3407,7 +3445,7 @@ void GdbEngine::updateLocals()
|
||||
postCommand(cmd, WatchUpdate, CB(handleStackListArguments));
|
||||
// '2' is 'list with type and value'
|
||||
postCommand(_("-stack-list-locals 2"), WatchUpdate,
|
||||
CB(handleStackListLocals)); // stage 2/2
|
||||
CB(handleStackListLocals), cookie); // stage 2/2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3434,7 +3472,7 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response)
|
||||
out = m_firstChunk + out;
|
||||
int pos = out.indexOf("locals=");
|
||||
if (pos != 0) {
|
||||
qDebug() << "DICARDING JUNK AT BEGIN OF RESPONSE: "
|
||||
qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: "
|
||||
<< out.left(pos);
|
||||
out = out.mid(pos);
|
||||
}
|
||||
@@ -3455,7 +3493,9 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response)
|
||||
// qDebug() << "READ: " << list.at(i).toString();
|
||||
manager()->watchHandler()->insertBulkData(list);
|
||||
|
||||
manager()->watchHandler()->updateWatchers();
|
||||
// FIXME:
|
||||
//manager()->watchHandler()->updateWatchers();
|
||||
rebuildModel();
|
||||
} else {
|
||||
QTC_ASSERT(false, /**/);
|
||||
}
|
||||
@@ -3503,91 +3543,105 @@ void GdbEngine::handleStackListLocals(const GdbResponse &response)
|
||||
// There could be shadowed variables
|
||||
QList<GdbMi> locals = response.data.findChild("locals").children();
|
||||
locals += m_currentFunctionArgs;
|
||||
|
||||
setLocals(locals);
|
||||
QMap<QByteArray, int> seen;
|
||||
// If desired, retrieve list of uninitialized variables looking at
|
||||
// the current frame. This is invoked first time after a stop from
|
||||
// handleStop2, which passes on the frame as cookie. The whole stack
|
||||
// is not known at this point.
|
||||
QStringList uninitializedVariables;
|
||||
if (theDebuggerAction(UseCodeModel)->isChecked()) {
|
||||
const StackFrame frame = qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) ?
|
||||
qVariantValue<Debugger::Internal::StackFrame>(response.cookie) :
|
||||
m_manager->stackHandler()->currentFrame();
|
||||
if (frame.isUsable())
|
||||
getUninitializedVariables(m_manager->cppCodeModelSnapshot(),
|
||||
frame.function, frame.file, frame.line,
|
||||
&uninitializedVariables);
|
||||
}
|
||||
QList<WatchData> list;
|
||||
foreach (const GdbMi &item, locals) {
|
||||
const WatchData data = localVariable(item, uninitializedVariables, &seen);
|
||||
if (data.isValid())
|
||||
list.push_back(data);
|
||||
}
|
||||
manager()->watchHandler()->insertBulkData(list);
|
||||
manager()->watchHandler()->updateWatchers();
|
||||
}
|
||||
|
||||
void GdbEngine::setLocals(const QList<GdbMi> &locals)
|
||||
// Parse a local variable from GdbMi
|
||||
WatchData GdbEngine::localVariable(const GdbMi &item,
|
||||
const QStringList &uninitializedVariables,
|
||||
QMap<QByteArray, int> *seen)
|
||||
{
|
||||
//qDebug() << m_varToType;
|
||||
QMap<QByteArray, int> seen;
|
||||
|
||||
QList<WatchData> list;
|
||||
foreach (const GdbMi &item, locals) {
|
||||
// Local variables of inlined code are reported as
|
||||
// 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
|
||||
// numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..."
|
||||
// We do not want these at all. Current hypotheses is that those
|
||||
// "spurious" locals have _two_ "exp" field. Try to filter them:
|
||||
#ifdef Q_OS_MAC
|
||||
int numExps = 0;
|
||||
foreach (const GdbMi &child, item.children())
|
||||
numExps += int(child.name() == "exp");
|
||||
if (numExps > 1)
|
||||
continue;
|
||||
QByteArray name = item.findChild("exp").data();
|
||||
#else
|
||||
QByteArray name = item.findChild("name").data();
|
||||
#endif
|
||||
int n = seen.value(name);
|
||||
if (n) {
|
||||
seen[name] = n + 1;
|
||||
WatchData data;
|
||||
QString nam = _(name);
|
||||
data.iname = _("local.") + nam + QString::number(n + 1);
|
||||
//: Variable %1 is the variable name, %2 is a simple count
|
||||
data.name = tr("%1 <shadowed %2>").arg(nam).arg(n);
|
||||
// Local variables of inlined code are reported as
|
||||
// 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
|
||||
// numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..."}}
|
||||
// We do not want these at all. Current hypotheses is that those
|
||||
// "spurious" locals have _two_ "exp" field. Try to filter them:
|
||||
#ifdef Q_OS_MAC
|
||||
int numExps = 0;
|
||||
foreach (const GdbMi &child, item.children())
|
||||
numExps += int(child.name() == "exp");
|
||||
if (numExps > 1)
|
||||
return WatchData();
|
||||
QByteArray name = item.findChild("exp").data();
|
||||
#else
|
||||
QByteArray name = item.findChild("name").data();
|
||||
#endif
|
||||
const QMap<QByteArray, int>::iterator it = seen->find(name);
|
||||
if (it != seen->end()) {
|
||||
const int n = it.value();
|
||||
++(it.value());
|
||||
WatchData data;
|
||||
QString nam = _(name);
|
||||
data.iname = _("local.") + nam + QString::number(n + 1);
|
||||
//: Variable %1 is the variable name, %2 is a simple count
|
||||
data.name = WatchData::shadowedName(nam, n);
|
||||
if (uninitializedVariables.contains(data.name)) {
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
return data;
|
||||
}
|
||||
//: Type of local variable or parameter shadowed by another
|
||||
//: variable of the same name in a nested block.
|
||||
setWatchDataValue(data, item.findChild("value"));
|
||||
data.setType(GdbEngine::tr("<shadowed>"));
|
||||
data.setHasChildren(false);
|
||||
return data;
|
||||
}
|
||||
seen->insert(name, 1);
|
||||
WatchData data;
|
||||
QString nam = _(name);
|
||||
data.iname = _("local.") + nam;
|
||||
data.name = nam;
|
||||
data.exp = nam;
|
||||
data.framekey = m_currentFrame + data.name;
|
||||
setWatchDataType(data, item.findChild("type"));
|
||||
if (uninitializedVariables.contains(data.name)) {
|
||||
data.setError(WatchData::msgNotInScope());
|
||||
return data;
|
||||
}
|
||||
if (isSynchroneous()) {
|
||||
setWatchDataValue(data, item.findChild("value"),
|
||||
item.findChild("valueencoded").data().toInt());
|
||||
// We know that the complete list of children is
|
||||
// somewhere in the response.
|
||||
data.setChildrenUnneeded();
|
||||
} else {
|
||||
// set value only directly if it is simple enough, otherwise
|
||||
// pass through the insertData() machinery
|
||||
if (isIntOrFloatType(data.type) || isPointerType(data.type))
|
||||
setWatchDataValue(data, item.findChild("value"));
|
||||
if (isSymbianIntType(data.type)) {
|
||||
setWatchDataValue(data, item.findChild("value"));
|
||||
//: Type of local variable or parameter shadowed by another
|
||||
//variable of the same name in a nested block
|
||||
data.setType(tr("<shadowed>"));
|
||||
data.setHasChildren(false);
|
||||
list.append(data);
|
||||
} else {
|
||||
seen[name] = 1;
|
||||
WatchData data;
|
||||
QString nam = _(name);
|
||||
data.iname = _("local.") + nam;
|
||||
data.name = nam;
|
||||
data.exp = nam;
|
||||
data.framekey = m_currentFrame + data.name;
|
||||
setWatchDataType(data, item.findChild("type"));
|
||||
if (isSynchroneous()) {
|
||||
setWatchDataValue(data, item.findChild("value"),
|
||||
item.findChild("valueencoded").data().toInt());
|
||||
// We know that the complete list of children is
|
||||
// somewhere in the response.
|
||||
data.setChildrenUnneeded();
|
||||
} else {
|
||||
// set value only directly if it is simple enough, otherwise
|
||||
// pass through the insertData() machinery
|
||||
if (isIntOrFloatType(data.type) || isPointerType(data.type))
|
||||
setWatchDataValue(data, item.findChild("value"));
|
||||
if (isSymbianIntType(data.type)) {
|
||||
setWatchDataValue(data, item.findChild("value"));
|
||||
data.setHasChildren(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's be a bit more bold:
|
||||
//if (!hasDebuggingHelperForType(data.type)) {
|
||||
// QByteArray value = item.findChild("value").data();
|
||||
// if (!value.isEmpty() && value != "{...}")
|
||||
// data.setValue(decodeData(value, 0));
|
||||
//}
|
||||
if (!manager()->watchHandler()->isExpandedIName(data.iname))
|
||||
data.setChildrenUnneeded();
|
||||
if (isPointerType(data.type) || data.name == __("this"))
|
||||
data.setHasChildren(true);
|
||||
if (0 && m_varToType.contains(data.framekey)) {
|
||||
qDebug() << "RE-USING" << m_varToType.value(data.framekey);
|
||||
data.setType(m_varToType.value(data.framekey));
|
||||
}
|
||||
list.append(data);
|
||||
}
|
||||
}
|
||||
manager()->watchHandler()->insertBulkData(list);
|
||||
|
||||
if (!m_manager->watchHandler()->isExpandedIName(data.iname))
|
||||
data.setChildrenUnneeded();
|
||||
if (isPointerType(data.type) || data.name == __("this"))
|
||||
data.setHasChildren(true);
|
||||
return data;
|
||||
}
|
||||
|
||||
void GdbEngine::insertData(const WatchData &data0)
|
||||
@@ -4112,9 +4166,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResponse &response)
|
||||
|
||||
void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
||||
{
|
||||
lastFile = frame.file;
|
||||
lastLine = frame.line;
|
||||
//qDebug() << "GOTO " << frame.toString() << setMarker;
|
||||
// qDebug() << "GOTO " << frame << setMarker;
|
||||
m_manager->gotoLocation(frame, setMarker);
|
||||
}
|
||||
|
||||
@@ -4122,18 +4174,37 @@ void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
||||
// Starting up & shutting down
|
||||
//
|
||||
|
||||
void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
|
||||
bool GdbEngine::startGdb(const QStringList &args, const QString &gdb)
|
||||
{
|
||||
setState(AdapterStartFailed);
|
||||
debugMessage(_("ADAPTER START FAILED"));
|
||||
Core::ICore::instance()->showWarningWithOptions(tr("Adapter start failed"), msg, QString(),
|
||||
QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
|
||||
shutdown();
|
||||
}
|
||||
debugMessage(_("STARTING GDB ") + gdb);
|
||||
|
||||
void GdbEngine::handleAdapterStarted()
|
||||
{
|
||||
debugMessage(_("ADAPTER SUCCESSFULLY STARTED, INITIALIZING GDB"));
|
||||
m_gdbProc.disconnect(); // From any previous runs
|
||||
|
||||
QString location = gdb;
|
||||
if (location.isEmpty())
|
||||
location = theDebuggerStringSetting(GdbLocation);
|
||||
QStringList gdbArgs;
|
||||
gdbArgs << _("-i");
|
||||
gdbArgs << _("mi");
|
||||
gdbArgs += args;
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
|
||||
if (!m_gdbProc.waitForStarted()) {
|
||||
handleAdapterStartFailed(m_gdbProc.errorString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do this only after the process is running, so we get no needless error notifications
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
SLOT(handleGdbError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
SLOT(readGdbStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
SLOT(readGdbStandardError()));
|
||||
|
||||
debugMessage(_("GDB STARTED, INITIALIZING IT"));
|
||||
|
||||
postCommand(_("show version"), CB(handleShowVersion));
|
||||
postCommand(_("help bb"), CB(handleIsSynchroneous));
|
||||
@@ -4217,20 +4288,82 @@ void GdbEngine::handleAdapterStarted()
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("HANDLE GDB ERROR"));
|
||||
switch (error) {
|
||||
case QProcess::Crashed:
|
||||
break; // will get a processExited() as well
|
||||
// impossible case QProcess::FailedToStart:
|
||||
case QProcess::ReadError:
|
||||
case QProcess::WriteError:
|
||||
case QProcess::Timedout:
|
||||
default:
|
||||
m_gdbProc.terminate();
|
||||
setState(EngineShuttingDown, true);
|
||||
showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"),
|
||||
errorMessage(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbFinished(int code, QProcess::ExitStatus type)
|
||||
{
|
||||
debugMessage(_("GDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
|
||||
if (state() == EngineShuttingDown) {
|
||||
m_gdbAdapter->shutdown();
|
||||
} else if (state() != AdapterStartFailed) {
|
||||
showMessageBox(QMessageBox::Critical, tr("Unexpected Gdb Exit"),
|
||||
tr("The gdb process exited unexpectedly (%1).")
|
||||
.arg((type == QProcess::CrashExit)
|
||||
? tr("crashed") : tr("code %1").arg(code)));
|
||||
m_gdbAdapter->shutdown();
|
||||
}
|
||||
initializeVariables();
|
||||
setState(DebuggerNotReady, true);
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
|
||||
{
|
||||
setState(AdapterStartFailed);
|
||||
debugMessage(_("ADAPTER START FAILED"));
|
||||
Core::ICore::instance()->showWarningWithOptions(
|
||||
tr("Adapter start failed"), msg, QString(),
|
||||
_(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterStarted()
|
||||
{
|
||||
setState(AdapterStarted);
|
||||
debugMessage(_("ADAPTER SUCCESSFULLY STARTED"));
|
||||
|
||||
showStatusMessage(tr("Starting inferior..."));
|
||||
setState(InferiorStarting);
|
||||
m_gdbAdapter->startInferior();
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorPrepared()
|
||||
{
|
||||
// Initial attempt to set breakpoints
|
||||
showStatusMessage(tr("Setting breakpoints..."));
|
||||
attemptBreakpointSynchronization();
|
||||
|
||||
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
|
||||
m_commandsDoneCallback = &GdbEngine::startInferior;
|
||||
if (m_cookieForToken.isEmpty()) {
|
||||
startInferiorPhase2();
|
||||
} else {
|
||||
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
|
||||
m_commandsDoneCallback = &GdbEngine::startInferiorPhase2;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::startInferior()
|
||||
void GdbEngine::startInferiorPhase2()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
|
||||
showStatusMessage(tr("Starting inferior..."));
|
||||
setState(InferiorStarting);
|
||||
m_gdbAdapter->startInferior();
|
||||
debugMessage(_("BREAKPOINTS SET, CONTINUING INFERIOR STARTUP"));
|
||||
m_gdbAdapter->startInferiorPhase2();
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorStartFailed(const QString &msg)
|
||||
@@ -4241,46 +4374,22 @@ void GdbEngine::handleInferiorStartFailed(const QString &msg)
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorShutDown()
|
||||
{
|
||||
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
|
||||
}
|
||||
|
||||
void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
|
||||
{
|
||||
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
|
||||
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
|
||||
shutdown(); // continue with adapter shutdown
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterCrashed(const QString &msg)
|
||||
{
|
||||
debugMessage(_("ADAPTER CRASHED"));
|
||||
switch (state()) {
|
||||
// All fall-through.
|
||||
case InferiorRunning:
|
||||
setState(InferiorShuttingDown);
|
||||
case InferiorShuttingDown:
|
||||
setState(InferiorShutDown);
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
default:
|
||||
setState(DebuggerNotReady);
|
||||
}
|
||||
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterShutDown()
|
||||
{
|
||||
debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN"));
|
||||
setState(DebuggerNotReady);
|
||||
}
|
||||
// The adapter is expected to have cleaned up after itself when we get here,
|
||||
// so the effect is about the same as AdapterStartFailed => use it.
|
||||
// Don't bother with state transitions - this can happen in any state and
|
||||
// the end result is always the same, so it makes little sense to find a
|
||||
// "path" which does not assert.
|
||||
setState(AdapterStartFailed, true);
|
||||
|
||||
void GdbEngine::handleAdapterShutdownFailed(const QString &msg)
|
||||
{
|
||||
debugMessage(_("ADAPTER SHUTDOWN FAILED"));
|
||||
showMessageBox(QMessageBox::Critical, tr("Adapter shutdown failed"), msg);
|
||||
setState(DebuggerNotReady);
|
||||
// No point in being friendly here ...
|
||||
m_gdbProc.terminate();
|
||||
|
||||
if (!msg.isEmpty())
|
||||
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
|
||||
}
|
||||
|
||||
void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const
|
||||
@@ -4314,4 +4423,3 @@ IDebuggerEngine *createGdbEngine(DebuggerManager *manager)
|
||||
Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgentCookie);
|
||||
Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie);
|
||||
Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);
|
||||
|
||||
|
@@ -92,84 +92,79 @@ private:
|
||||
friend class AttachGdbAdapter;
|
||||
friend class CoreGdbAdapter;
|
||||
friend class PlainGdbAdapter;
|
||||
friend class TermGdbAdapter;
|
||||
friend class RemoteGdbAdapter;
|
||||
friend class TrkGdbAdapter;
|
||||
|
||||
//
|
||||
// IDebuggerEngine implementation
|
||||
//
|
||||
void stepExec();
|
||||
void stepOutExec();
|
||||
void nextExec();
|
||||
void stepIExec();
|
||||
void nextIExec();
|
||||
private: ////////// General Interface //////////
|
||||
|
||||
void shutdown();
|
||||
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
|
||||
void startDebugger(const DebuggerStartParametersPtr &sp);
|
||||
void exitDebugger();
|
||||
void detachDebugger();
|
||||
virtual void addOptionPages(QList<Core::IOptionsPage*> *opts) const;
|
||||
|
||||
void continueInferiorInternal();
|
||||
void autoContinueInferior();
|
||||
void continueInferior();
|
||||
void interruptInferior();
|
||||
virtual bool checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage= 0) const;
|
||||
|
||||
void runToLineExec(const QString &fileName, int lineNumber);
|
||||
void runToFunctionExec(const QString &functionName);
|
||||
void jumpToLineExec(const QString &fileName, int lineNumber);
|
||||
virtual bool isGdbEngine() const { return true; }
|
||||
|
||||
void activateFrame(int index);
|
||||
void selectThread(int index);
|
||||
virtual void startDebugger(const DebuggerStartParametersPtr &sp);
|
||||
virtual void exitDebugger();
|
||||
virtual void detachDebugger();
|
||||
virtual void shutdown();
|
||||
|
||||
Q_SLOT void attemptBreakpointSynchronization();
|
||||
virtual void executeDebuggerCommand(const QString &command);
|
||||
|
||||
void assignValueInDebugger(const QString &expr, const QString &value);
|
||||
void executeDebuggerCommand(const QString & command);
|
||||
void watchPoint(const QPoint &);
|
||||
private: ////////// General State //////////
|
||||
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
|
||||
|
||||
void fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length);
|
||||
void handleFetchMemory(const GdbResponse &response);
|
||||
|
||||
void fetchDisassembler(DisassemblerViewAgent *agent,
|
||||
const StackFrame &frame);
|
||||
void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
|
||||
bool useMixedMode);
|
||||
void handleFetchDisassemblerByLine(const GdbResponse &response);
|
||||
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
|
||||
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
|
||||
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
|
||||
Q_SLOT void setAutoDerefPointers(const QVariant &on);
|
||||
bool isGdbEngine() const { return true; }
|
||||
bool isSynchroneous() const;
|
||||
|
||||
bool checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage= 0) const;
|
||||
|
||||
//
|
||||
// Own stuff
|
||||
//
|
||||
|
||||
int currentFrame() const;
|
||||
|
||||
bool supportsThreads() const;
|
||||
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
|
||||
StackFrame parseStackFrame(const GdbMi &mi, int level);
|
||||
|
||||
void connectAdapter();
|
||||
void initializeVariables();
|
||||
QString fullName(const QString &fileName);
|
||||
// get one usable name out of these, try full names first
|
||||
QString fullName(const QStringList &candidates);
|
||||
DebuggerStartMode startMode() const;
|
||||
const DebuggerStartParameters &startParameters() const
|
||||
{ return *m_startParameters; }
|
||||
Q_SLOT void setAutoDerefPointers(const QVariant &on);
|
||||
|
||||
void handleResult(const GdbResponse &response);
|
||||
DebuggerStartParametersPtr m_startParameters;
|
||||
QSharedPointer<TrkOptions> m_trkOptions;
|
||||
|
||||
public: // otherwise the Qt flag macros are unhappy
|
||||
private: ////////// Gdb Process Management //////////
|
||||
|
||||
AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp);
|
||||
void connectAdapter();
|
||||
bool startGdb(const QStringList &args = QStringList(), const QString &gdb = QString());
|
||||
void startInferiorPhase2();
|
||||
|
||||
void handleInferiorShutdown(const GdbResponse &response);
|
||||
void handleGdbExit(const GdbResponse &response);
|
||||
|
||||
void gdbInputAvailable(int channel, const QString &msg)
|
||||
{ m_manager->showDebuggerInput(channel, msg); }
|
||||
void gdbOutputAvailable(int channel, const QString &msg)
|
||||
{ m_manager->showDebuggerOutput(channel, msg); }
|
||||
|
||||
private slots:
|
||||
void handleGdbFinished(int, QProcess::ExitStatus status);
|
||||
void handleGdbError(QProcess::ProcessError error);
|
||||
void readGdbStandardOutput();
|
||||
void readGdbStandardError();
|
||||
void readDebugeeOutput(const QByteArray &data);
|
||||
|
||||
void handleAdapterStarted();
|
||||
void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
|
||||
|
||||
void handleInferiorPrepared();
|
||||
|
||||
void handleInferiorStartFailed(const QString &msg);
|
||||
|
||||
void handleAdapterCrashed(const QString &msg);
|
||||
|
||||
private:
|
||||
QTextCodec *m_outputCodec;
|
||||
QTextCodec::ConverterState m_outputCodecState;
|
||||
|
||||
QByteArray m_inbuffer;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
AbstractGdbAdapter *m_gdbAdapter;
|
||||
|
||||
private: ////////// Gdb Command Management //////////
|
||||
|
||||
public: // otherwise the Qt flag macros are unhappy
|
||||
enum GdbCommandFlag {
|
||||
NoFlags = 0,
|
||||
NeedsStop = 1, // The command needs a stopped inferior
|
||||
@@ -181,9 +176,8 @@ public: // otherwise the Qt flag macros are unhappy
|
||||
ExitRequest = 32 // Callback expect GdbResultExit instead of GdbResultDone
|
||||
};
|
||||
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
||||
private:
|
||||
|
||||
|
||||
private:
|
||||
typedef void (GdbEngine::*GdbCommandCallback)
|
||||
(const GdbResponse &response);
|
||||
typedef void (AbstractGdbAdapter::*AdapterCallback)
|
||||
@@ -230,65 +224,7 @@ private:
|
||||
void postCommandHelper(const GdbCommand &cmd);
|
||||
void setTokenBarrier();
|
||||
|
||||
void updateAll();
|
||||
void updateLocals();
|
||||
|
||||
void gdbInputAvailable(int channel, const QString &msg)
|
||||
{ m_manager->showDebuggerInput(channel, msg); }
|
||||
void gdbOutputAvailable(int channel, const QString &msg)
|
||||
{ m_manager->showDebuggerOutput(channel, msg); }
|
||||
|
||||
private slots:
|
||||
void readGdbStandardOutput();
|
||||
void readGdbStandardError();
|
||||
void readDebugeeOutput(const QByteArray &data);
|
||||
|
||||
void handleAdapterStarted();
|
||||
void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
|
||||
|
||||
void handleInferiorStartFailed(const QString &msg);
|
||||
void handleInferiorShutDown();
|
||||
void handleInferiorShutdownFailed(const QString &msg);
|
||||
|
||||
void handleAdapterCrashed(const QString &msg);
|
||||
void handleAdapterShutDown();
|
||||
void handleAdapterShutdownFailed(const QString &msg);
|
||||
|
||||
private:
|
||||
int terminationIndex(const QByteArray &buffer, int &length);
|
||||
void handleResponse(const QByteArray &buff);
|
||||
void handleStopResponse(const GdbMi &data);
|
||||
void handleStop1(const GdbResponse &response);
|
||||
void handleStop1(const GdbMi &data);
|
||||
void handleStop2(const GdbResponse &response);
|
||||
void handleStop2(const GdbMi &data);
|
||||
void handleResultRecord(const GdbResponse &response);
|
||||
void handleExecContinue(const GdbResponse &response);
|
||||
// void handleExecRunToFunction(const GdbResponse &response);
|
||||
void handleInfoShared(const GdbResponse &response);
|
||||
void handleShowVersion(const GdbResponse &response);
|
||||
void handleQuerySources(const GdbResponse &response);
|
||||
void handleWatchPoint(const GdbResponse &response);
|
||||
void handleIsSynchroneous(const GdbResponse &response);
|
||||
bool showToolTip();
|
||||
|
||||
// Convenience
|
||||
QMainWindow *mainWindow() const;
|
||||
DebuggerStartMode startMode() const;
|
||||
qint64 inferiorPid() const { return m_manager->inferiorPid(); }
|
||||
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
|
||||
|
||||
void handleChildren(const WatchData &parent, const GdbMi &child,
|
||||
QList<WatchData> *insertions);
|
||||
const bool m_dumperInjectionLoad;
|
||||
|
||||
QTextCodec *m_outputCodec;
|
||||
QTextCodec::ConverterState m_outputCodecState;
|
||||
|
||||
QByteArray m_inbuffer;
|
||||
|
||||
QHash<int, GdbCommand> m_cookieForToken;
|
||||
QHash<int, QByteArray> m_customOutputForToken;
|
||||
|
||||
QByteArray m_pendingConsoleStreamOutput;
|
||||
QByteArray m_pendingLogStreamOutput;
|
||||
@@ -298,13 +234,68 @@ private:
|
||||
// out of date and discarded.
|
||||
int m_oldestAcceptableToken;
|
||||
|
||||
int m_pendingRequests; // Watch updating commands in flight
|
||||
|
||||
typedef void (GdbEngine::*CommandsDoneCallback)();
|
||||
// function called after all previous responses have been received
|
||||
CommandsDoneCallback m_commandsDoneCallback;
|
||||
|
||||
QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
|
||||
|
||||
private: ////////// Gdb Output, State & Capability Handling //////////
|
||||
|
||||
void handleResponse(const QByteArray &buff);
|
||||
void handleStopResponse(const GdbMi &data);
|
||||
void handleResultRecord(const GdbResponse &response);
|
||||
void handleStop1(const GdbResponse &response);
|
||||
void handleStop1(const GdbMi &data);
|
||||
void handleStop2(const GdbResponse &response);
|
||||
void handleStop2(const GdbMi &data);
|
||||
StackFrame parseStackFrame(const GdbMi &mi, int level);
|
||||
|
||||
virtual bool isSynchroneous() const;
|
||||
bool supportsThreads() const;
|
||||
|
||||
// Gdb initialization sequence
|
||||
void handleShowVersion(const GdbResponse &response);
|
||||
void handleIsSynchroneous(const GdbResponse &response);
|
||||
|
||||
int m_gdbVersion; // 6.8.0 is 680
|
||||
int m_gdbBuildVersion; // MAC only?
|
||||
bool m_isSynchroneous; // Can act synchroneously?
|
||||
|
||||
// awful hack to keep track of used files
|
||||
QMap<QString, QString> m_shortToFullName;
|
||||
QMap<QString, QString> m_fullToShortName;
|
||||
private: ////////// Inferior Management //////////
|
||||
|
||||
Q_SLOT virtual void attemptBreakpointSynchronization();
|
||||
|
||||
virtual void stepExec();
|
||||
virtual void stepOutExec();
|
||||
virtual void nextExec();
|
||||
virtual void stepIExec();
|
||||
virtual void nextIExec();
|
||||
|
||||
void continueInferiorInternal();
|
||||
void autoContinueInferior();
|
||||
virtual void continueInferior();
|
||||
virtual void interruptInferior();
|
||||
|
||||
virtual void runToLineExec(const QString &fileName, int lineNumber);
|
||||
virtual void runToFunctionExec(const QString &functionName);
|
||||
// void handleExecRunToFunction(const GdbResponse &response);
|
||||
virtual void jumpToLineExec(const QString &fileName, int lineNumber);
|
||||
|
||||
void handleExecContinue(const GdbResponse &response);
|
||||
|
||||
qint64 inferiorPid() const { return m_manager->inferiorPid(); }
|
||||
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
|
||||
void maybeHandleInferiorPidChanged(const QString &pid);
|
||||
|
||||
private: ////////// View & Data Stuff //////////
|
||||
|
||||
virtual void selectThread(int index);
|
||||
virtual void activateFrame(int index);
|
||||
|
||||
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
|
||||
|
||||
//
|
||||
// Breakpoint specific stuff
|
||||
@@ -323,9 +314,13 @@ private:
|
||||
//
|
||||
// Modules specific stuff
|
||||
//
|
||||
virtual void loadSymbols(const QString &moduleName);
|
||||
virtual void loadAllSymbols();
|
||||
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
|
||||
void reloadModules();
|
||||
void handleModulesList(const GdbResponse &response);
|
||||
|
||||
bool m_modulesListOutdated;
|
||||
|
||||
//
|
||||
// Register specific stuff
|
||||
@@ -335,54 +330,83 @@ private:
|
||||
void handleRegisterListNames(const GdbResponse &response);
|
||||
void handleRegisterListValues(const GdbResponse &response);
|
||||
|
||||
//
|
||||
// Disassembler specific stuff
|
||||
//
|
||||
virtual void fetchDisassembler(DisassemblerViewAgent *agent,
|
||||
const StackFrame &frame);
|
||||
void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
|
||||
bool useMixedMode);
|
||||
void handleFetchDisassemblerByLine(const GdbResponse &response);
|
||||
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
|
||||
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
|
||||
QString parseDisassembler(const GdbMi &lines);
|
||||
|
||||
//
|
||||
// Source file specific stuff
|
||||
//
|
||||
void reloadSourceFiles();
|
||||
void handleQuerySources(const GdbResponse &response);
|
||||
|
||||
QString fullName(const QString &fileName);
|
||||
// get one usable name out of these, try full names first
|
||||
QString fullName(const QStringList &candidates);
|
||||
|
||||
// awful hack to keep track of used files
|
||||
QMap<QString, QString> m_shortToFullName;
|
||||
QMap<QString, QString> m_fullToShortName;
|
||||
|
||||
//
|
||||
// Stack specific stuff
|
||||
//
|
||||
void updateAll();
|
||||
void handleStackListFrames(const GdbResponse &response);
|
||||
void handleStackSelectThread(const GdbResponse &response);
|
||||
void handleStackListThreads(const GdbResponse &response);
|
||||
void handleStackFrame1(const GdbResponse &response);
|
||||
void handleStackFrame2(const GdbResponse &response);
|
||||
QByteArray m_firstChunk;
|
||||
Q_SLOT void reloadStack(bool forceGotoLocation);
|
||||
Q_SLOT void reloadFullStack();
|
||||
int currentFrame() const;
|
||||
|
||||
|
||||
//
|
||||
// Tooltip specific stuff
|
||||
//
|
||||
void sendToolTipCommand(const QString &command, const QString &cookie);
|
||||
|
||||
QList<GdbMi> m_currentFunctionArgs;
|
||||
QByteArray m_firstChunk;
|
||||
QString m_currentFrame;
|
||||
|
||||
//
|
||||
// Watch specific stuff
|
||||
//
|
||||
virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
|
||||
|
||||
virtual void assignValueInDebugger(const QString &expr, const QString &value);
|
||||
|
||||
virtual void fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length);
|
||||
void handleFetchMemory(const GdbResponse &response);
|
||||
|
||||
virtual void watchPoint(const QPoint &);
|
||||
void handleWatchPoint(const GdbResponse &response);
|
||||
|
||||
// FIXME: BaseClass. called to improve situation for a watch item
|
||||
void updateSubItem(const WatchData &data);
|
||||
void handleChildren(const WatchData &parent, const GdbMi &child,
|
||||
QList<WatchData> *insertions);
|
||||
|
||||
void updateWatchData(const WatchData &data);
|
||||
Q_SLOT void updateWatchDataHelper(const WatchData &data);
|
||||
void rebuildModel();
|
||||
bool showToolTip();
|
||||
|
||||
void insertData(const WatchData &data);
|
||||
void sendWatchParameters(const QByteArray ¶ms0);
|
||||
void createGdbVariable(const WatchData &data);
|
||||
|
||||
void maybeHandleInferiorPidChanged(const QString &pid);
|
||||
|
||||
void tryLoadDebuggingHelpers();
|
||||
void tryQueryDebuggingHelpers();
|
||||
Q_SLOT void recheckDebuggingHelperAvailability();
|
||||
void runDebuggingHelper(const WatchData &data, bool dumpChildren);
|
||||
void runDirectDebuggingHelper(const WatchData &data, bool dumpChildren);
|
||||
bool hasDebuggingHelperForType(const QString &type) const;
|
||||
|
||||
void handleVarListChildren(const GdbResponse &response);
|
||||
void handleVarListChildrenHelper(const GdbMi &child,
|
||||
const WatchData &parent);
|
||||
void handleVarCreate(const GdbResponse &response);
|
||||
void handleVarAssign(const GdbResponse &response);
|
||||
void handleEvaluateExpression(const GdbResponse &response);
|
||||
@@ -393,53 +417,42 @@ private:
|
||||
void handleDebuggingHelperValue3(const GdbResponse &response);
|
||||
void handleDebuggingHelperEditValue(const GdbResponse &response);
|
||||
void handleDebuggingHelperSetup(const GdbResponse &response);
|
||||
|
||||
void updateLocals(const QVariant &cookie = QVariant());
|
||||
void handleStackListLocals(const GdbResponse &response);
|
||||
WatchData localVariable(const GdbMi &item,
|
||||
const QStringList &uninitializedVariables,
|
||||
QMap<QByteArray, int> *seen);
|
||||
void setLocals(const QList<GdbMi> &locals);
|
||||
void handleStackListArguments(const GdbResponse &response);
|
||||
void handleVarListChildrenHelper(const GdbMi &child,
|
||||
const WatchData &parent);
|
||||
void setWatchDataType(WatchData &data, const GdbMi &mi);
|
||||
void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);
|
||||
void setLocals(const QList<GdbMi> &locals);
|
||||
void connectDebuggingHelperActions();
|
||||
void disconnectDebuggingHelperActions();
|
||||
AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp);
|
||||
|
||||
bool startModeAllowsDumpers() const;
|
||||
QString parseDisassembler(const GdbMi &lines);
|
||||
|
||||
int m_pendingRequests;
|
||||
QSet<QString> m_processedNames;
|
||||
|
||||
QtDumperHelper m_dumperHelper;
|
||||
|
||||
DebuggingHelperState m_debuggingHelperState;
|
||||
QList<GdbMi> m_currentFunctionArgs;
|
||||
QString m_currentFrame;
|
||||
QMap<QString, QString> m_varToType;
|
||||
|
||||
typedef void (GdbEngine::*CommandsDoneCallback)();
|
||||
// function called after all previous responses have been received
|
||||
CommandsDoneCallback m_commandsDoneCallback;
|
||||
void startInferior();
|
||||
private: ////////// Dumper Management //////////
|
||||
|
||||
bool m_modulesListOutdated;
|
||||
bool startModeAllowsDumpers() const;
|
||||
void tryLoadDebuggingHelpers();
|
||||
void tryQueryDebuggingHelpers();
|
||||
Q_SLOT void recheckDebuggingHelperAvailability();
|
||||
void connectDebuggingHelperActions();
|
||||
void disconnectDebuggingHelperActions();
|
||||
Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
|
||||
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
|
||||
|
||||
QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
|
||||
const bool m_dumperInjectionLoad;
|
||||
DebuggingHelperState m_debuggingHelperState;
|
||||
QtDumperHelper m_dumperHelper;
|
||||
|
||||
DebuggerStartParametersPtr m_startParameters;
|
||||
// make sure to re-initialize new members in initializeVariables();
|
||||
private: ////////// Convenience Functions //////////
|
||||
|
||||
QSharedPointer<TrkOptions> m_trkOptions;
|
||||
|
||||
AbstractGdbAdapter *m_gdbAdapter;
|
||||
|
||||
public:
|
||||
QString errorMessage(QProcess::ProcessError error);
|
||||
void showMessageBox(int icon, const QString &title, const QString &text);
|
||||
void debugMessage(const QString &msg);
|
||||
void addOptionPages(QList<Core::IOptionsPage*> *opts) const;
|
||||
const DebuggerStartParameters &startParameters() const
|
||||
{ return *m_startParameters; }
|
||||
QMainWindow *mainWindow() const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -29,18 +29,13 @@
|
||||
|
||||
#include "plaingdbadapter.h"
|
||||
|
||||
#include "debuggeractions.h"
|
||||
#include "gdbengine.h"
|
||||
#include "procinterrupt.h"
|
||||
#include "debuggerstringutils.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/fancymainwindow.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -58,8 +53,6 @@ namespace Internal {
|
||||
PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
|
||||
// Output
|
||||
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
|
||||
engine, SLOT(readDebugeeOutput(QByteArray)));
|
||||
@@ -72,37 +65,27 @@ void PlainGdbAdapter::startAdapter()
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
|
||||
if (!m_outputCollector.listen()) {
|
||||
emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
|
||||
.arg(m_outputCollector.errorString()), QString());
|
||||
return;
|
||||
}
|
||||
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
|
||||
gdbArgs.append(_("--tty=") + m_outputCollector.serverName());
|
||||
|
||||
if (!startParameters().workingDir.isEmpty())
|
||||
m_gdbProc.setWorkingDirectory(startParameters().workingDir);
|
||||
m_engine->m_gdbProc.setWorkingDirectory(startParameters().workingDir);
|
||||
if (!startParameters().environment.isEmpty())
|
||||
m_gdbProc.setEnvironment(startParameters().environment);
|
||||
m_engine->m_gdbProc.setEnvironment(startParameters().environment);
|
||||
|
||||
m_gdbProc.start(theDebuggerStringSetting(GdbLocation), gdbArgs);
|
||||
}
|
||||
if (!m_engine->startGdb(gdbArgs)) {
|
||||
m_outputCollector.shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
setState(AdapterStarted);
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
@@ -118,9 +101,7 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
//m_breakHandler->clearBreakMarkers();
|
||||
setState(InferiorRunningRequested);
|
||||
m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
|
||||
emit inferiorPrepared();
|
||||
} else {
|
||||
QString msg = tr("Starting executable failed:\n") +
|
||||
__(response.data.findChild("msg").data());
|
||||
@@ -128,6 +109,12 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::startInferiorPhase2()
|
||||
{
|
||||
setState(InferiorRunningRequested);
|
||||
m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleExecRun(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultRunning) {
|
||||
@@ -160,74 +147,6 @@ void PlainGdbAdapter::shutdown()
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
|
||||
m_outputCollector.shutdown();
|
||||
switch (state()) {
|
||||
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
case InferiorStopping:
|
||||
case InferiorStopped:
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("kill"), CB(handleKill));
|
||||
return;
|
||||
|
||||
case InferiorShuttingDown:
|
||||
// FIXME: How can we end up here?
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
// Fall through.
|
||||
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
/*
|
||||
case InferiorShutdownFailed:
|
||||
m_gdbProc.terminate();
|
||||
// 20s can easily happen when loading webkit debug information
|
||||
m_gdbProc.waitForFinished(20000);
|
||||
setState(AdapterShuttingDown);
|
||||
debugMessage(_("FORCING TERMINATION: %1").arg(state()));
|
||||
if (state() != QProcess::NotRunning) {
|
||||
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
|
||||
.arg(state()));
|
||||
m_gdbProc.kill();
|
||||
}
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
*/
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleKill(const GdbResponse &response)
|
||||
{
|
||||
debugMessage(_("PLAIN ADAPTER HANDLE KILL " + response.toString()));
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void PlainGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROCESS FINISHED"));
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -31,11 +31,8 @@
|
||||
#define DEBUGGER_PLAINGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "outputcollector.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QProcess>
|
||||
#include <outputcollector.h>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -57,19 +54,15 @@ public:
|
||||
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void startInferiorPhase2();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
const char *inferiorShutdownCommand() const { return "kill"; }
|
||||
|
||||
private:
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleKill(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
void handleExecRun(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus status);
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbStarted();
|
||||
|
||||
OutputCollector m_outputCollector;
|
||||
};
|
||||
|
||||
|
@@ -28,8 +28,8 @@
|
||||
**************************************************************************/
|
||||
|
||||
#include "remotegdbadapter.h"
|
||||
|
||||
#include "debuggerstringutils.h"
|
||||
#include "debuggeractions.h"
|
||||
#include "gdbengine.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -54,8 +54,6 @@ namespace Internal {
|
||||
RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
commonInit();
|
||||
|
||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(uploadProcError(QProcess::ProcessError)));
|
||||
connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()),
|
||||
@@ -70,14 +68,6 @@ void RemoteGdbAdapter::startAdapter()
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.prepend(_("mi"));
|
||||
gdbArgs.prepend(_("-i"));
|
||||
|
||||
QString location = startParameters().debuggerCommand;
|
||||
if (location.isEmpty())
|
||||
location = theDebuggerStringSetting(GdbLocation);
|
||||
|
||||
// FIXME: make asynchroneous
|
||||
// Start the remote server
|
||||
if (startParameters().serverStartScript.isEmpty()) {
|
||||
@@ -88,33 +78,19 @@ void RemoteGdbAdapter::startAdapter()
|
||||
m_uploadProc.waitForStarted();
|
||||
}
|
||||
|
||||
// Start the debugger
|
||||
m_gdbProc.start(location, gdbArgs);
|
||||
}
|
||||
if (!m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
|
||||
// FIXME: cleanup missing
|
||||
return;
|
||||
|
||||
void RemoteGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
setState(AdapterStarted);
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
debugMessage(_("ADAPTER, HANDLE GDB ERROR"));
|
||||
emit adapterCrashed(m_engine->errorMessage(error));
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
|
||||
{
|
||||
QString msg;
|
||||
switch (error) {
|
||||
case QProcess::FailedToStart:
|
||||
msg = tr("The upload process failed to start. Either the "
|
||||
"invoked script '%1' is missing, or you may have insufficient "
|
||||
"permissions to invoke the program.")
|
||||
.arg(theDebuggerStringSetting(GdbLocation));
|
||||
msg = tr("The upload process failed to start. Shell missing?");
|
||||
break;
|
||||
case QProcess::Crashed:
|
||||
msg = tr("The upload process crashed some time after starting "
|
||||
@@ -140,7 +116,7 @@ void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
|
||||
}
|
||||
|
||||
m_engine->showStatusMessage(msg);
|
||||
QMessageBox::critical(m_engine->mainWindow(), tr("Error"), msg);
|
||||
showMessageBox(QMessageBox::Critical, tr("Error"), msg);
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::readUploadStandardOutput()
|
||||
@@ -211,7 +187,7 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
|
||||
// gdb server will stop the remote application itself.
|
||||
debugMessage(_("INFERIOR STARTED"));
|
||||
showStatusMessage(msgAttachedToStoppedInferior());
|
||||
m_engine->continueInferior();
|
||||
emit inferiorPrepared();
|
||||
} else {
|
||||
// 16^error,msg="hd:5555: Connection timed out."
|
||||
QString msg = msgConnectRemoteServerFailed(__(record.data.findChild("msg").data()));
|
||||
@@ -219,6 +195,11 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::startInferiorPhase2()
|
||||
{
|
||||
m_engine->continueInferiorInternal();
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::interruptInferior()
|
||||
{
|
||||
m_engine->postCommand(_("-exec-interrupt"));
|
||||
@@ -226,56 +207,7 @@ void RemoteGdbAdapter::interruptInferior()
|
||||
|
||||
void RemoteGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
|
||||
case InferiorRunning:
|
||||
case InferiorStopped:
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("kill"), CB(handleKill));
|
||||
return;
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
// fall through
|
||||
|
||||
case InferiorStartFailed:
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleKill(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
|
||||
{
|
||||
debugMessage(_("GDB PROESS FINISHED"));
|
||||
setState(DebuggerNotReady);
|
||||
emit adapterShutDown();
|
||||
// FIXME: cleanup missing
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -31,10 +31,6 @@
|
||||
#define DEBUGGER_REMOTEGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
@@ -56,6 +52,7 @@ public:
|
||||
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void startInferiorPhase2();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
|
||||
@@ -67,12 +64,6 @@ private:
|
||||
void handleSetTargetAsync(const GdbResponse &response);
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleTargetRemote(const GdbResponse &response);
|
||||
void handleKill(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
|
||||
|
||||
QProcess m_uploadProc;
|
||||
};
|
||||
|
154
src/plugins/debugger/gdb/termgdbadapter.cpp
Normal file
154
src/plugins/debugger/gdb/termgdbadapter.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "termgdbadapter.h"
|
||||
|
||||
#include "gdbengine.h"
|
||||
#include "procinterrupt.h"
|
||||
#include "debuggerstringutils.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtGui/QMessageBox>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&TermGdbAdapter::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TermGdbAdapter
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
TermGdbAdapter::TermGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||
: AbstractGdbAdapter(engine, parent)
|
||||
{
|
||||
m_stubProc.setMode(Utils::ConsoleProcess::Debug);
|
||||
#ifdef Q_OS_UNIX
|
||||
m_stubProc.setSettings(Core::ICore::instance()->settings());
|
||||
#endif
|
||||
|
||||
connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString)));
|
||||
connect(&m_stubProc, SIGNAL(processStarted()), SLOT(handleInferiorStarted()));
|
||||
connect(&m_stubProc, SIGNAL(wrapperStopped()), SLOT(stubExited()));
|
||||
}
|
||||
|
||||
TermGdbAdapter::~TermGdbAdapter()
|
||||
{
|
||||
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
|
||||
}
|
||||
|
||||
void TermGdbAdapter::startAdapter()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
|
||||
setState(AdapterStarting);
|
||||
debugMessage(_("TRYING TO START ADAPTER"));
|
||||
|
||||
// Currently, adapters are not re-used
|
||||
// // We leave the console open, so recycle it now.
|
||||
// m_stubProc.blockSignals(true);
|
||||
// m_stubProc.stop();
|
||||
// m_stubProc.blockSignals(false);
|
||||
|
||||
m_stubProc.setWorkingDirectory(startParameters().workingDir);
|
||||
m_stubProc.setEnvironment(startParameters().environment);
|
||||
// FIXME: Starting the stub implies starting the inferior. This is
|
||||
// fairly unclean as far as the state machine and error reporting go.
|
||||
if (!m_stubProc.start(startParameters().executable,
|
||||
startParameters().processArgs)) {
|
||||
// Error message for user is delivered via a signal.
|
||||
emit adapterStartFailed(QString(), QString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_engine->startGdb()) {
|
||||
m_stubProc.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void TermGdbAdapter::handleInferiorStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::startInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
const qint64 attachedPID = m_stubProc.applicationPID();
|
||||
m_engine->handleInferiorPidChanged(attachedPID);
|
||||
m_engine->postCommand(_("attach %1").arg(attachedPID), CB(handleStubAttached));
|
||||
}
|
||||
|
||||
void TermGdbAdapter::handleStubAttached(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
|
||||
debugMessage(_("INFERIOR ATTACHED"));
|
||||
emit inferiorPrepared();
|
||||
} else if (response.resultClass == GdbResultError) {
|
||||
QString msg = _(response.data.findChild("msg").data());
|
||||
emit inferiorStartFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TermGdbAdapter::startInferiorPhase2()
|
||||
{
|
||||
m_engine->continueInferiorInternal();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::interruptInferior()
|
||||
{
|
||||
debugMessage(_("TRYING TO INTERUPT INFERIOR"));
|
||||
const qint64 attachedPID = m_engine->inferiorPid();
|
||||
if (!interruptProcess(attachedPID))
|
||||
debugMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
|
||||
}
|
||||
|
||||
void TermGdbAdapter::stubError(const QString &msg)
|
||||
{
|
||||
showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg);
|
||||
}
|
||||
|
||||
void TermGdbAdapter::stubExited()
|
||||
{
|
||||
debugMessage(_("STUB EXITED"));
|
||||
if (state() != AdapterStarting // From previous instance
|
||||
&& state() != EngineShuttingDown && state() != DebuggerNotReady)
|
||||
emit adapterCrashed(QString());
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
74
src/plugins/debugger/gdb/termgdbadapter.h
Normal file
74
src/plugins/debugger/gdb/termgdbadapter.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef DEBUGGER_TERMGDBADAPTER_H
|
||||
#define DEBUGGER_TERMGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
|
||||
#include <consoleprocess.h>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TermGdbAdapter
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TermGdbAdapter : public AbstractGdbAdapter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TermGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||
~TermGdbAdapter();
|
||||
|
||||
bool dumpersAvailable() const { return true; }
|
||||
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void startInferiorPhase2();
|
||||
void interruptInferior();
|
||||
|
||||
private:
|
||||
void handleStubAttached(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleInferiorStarted();
|
||||
Q_SLOT void stubExited();
|
||||
Q_SLOT void stubError(const QString &msg);
|
||||
|
||||
Utils::ConsoleProcess m_stubProc;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_TERMGDBADAPTER_H
|
@@ -30,22 +30,24 @@
|
||||
#include "trkgdbadapter.h"
|
||||
#include "trkoptions.h"
|
||||
#include "trkoptionspage.h"
|
||||
|
||||
#include "debuggerstringutils.h"
|
||||
#ifndef STANDALONE_RUNNER
|
||||
#include "gdbengine.h"
|
||||
#endif
|
||||
#ifdef Q_OS_WIN
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \
|
||||
STRINGIFY(callback)
|
||||
@@ -204,10 +206,6 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
||||
#endif
|
||||
m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
|
||||
|
||||
commonInit();
|
||||
connect(&m_gdbProc, SIGNAL(stateChanged(QProcess::ProcessState)),
|
||||
this, SLOT(handleGdbStateChanged(QProcess::ProcessState)));
|
||||
|
||||
connect(&m_rfcommProc, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(handleRfcommReadyReadStandardError()));
|
||||
connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()),
|
||||
@@ -380,17 +378,6 @@ QByteArray TrkGdbAdapter::trkInterruptMessage()
|
||||
return ba;
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::emitDelayedAdapterStartFailed(const QString &msg)
|
||||
{
|
||||
m_adapterFailMessage = msg;
|
||||
QTimer::singleShot(0, this, SLOT(slotEmitDelayedAdapterStartFailed()));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::slotEmitDelayedAdapterStartFailed()
|
||||
{
|
||||
emit adapterStartFailed(m_adapterFailMessage, TrkOptionsPage::settingsId());
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::emitDelayedInferiorStartFailed(const QString &msg)
|
||||
{
|
||||
m_adapterFailMessage = msg;
|
||||
@@ -428,6 +415,7 @@ void TrkGdbAdapter::waitForTrkConnect()
|
||||
}
|
||||
|
||||
m_trkDevice.sendTrkInitialPing();
|
||||
sendTrkMessage(0x02); // Disconnect, as trk might be still connected
|
||||
sendTrkMessage(0x01); // Connect
|
||||
sendTrkMessage(0x05, TrkCB(handleSupportMask));
|
||||
sendTrkMessage(0x06, TrkCB(handleCpuType));
|
||||
@@ -437,7 +425,7 @@ void TrkGdbAdapter::waitForTrkConnect()
|
||||
// "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
|
||||
//sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
|
||||
|
||||
maybeAdapterStarted();
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::logMessage(const QString &msg)
|
||||
@@ -1527,52 +1515,6 @@ void TrkGdbAdapter::interruptInferior()
|
||||
sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||
{
|
||||
if (error == QProcess::FailedToStart) {
|
||||
const QString msg = QString::fromLatin1("GDB: Cannot start '%1': %2. Please check the settings.").arg(m_options->gdb).arg(m_gdbProc.errorString());
|
||||
emitDelayedAdapterStartFailed(msg); // Emitted from QProcess::start() on Windows
|
||||
} else {
|
||||
// Others should trigger handleGdbFinished
|
||||
const QString msg = QString::fromLatin1("GDB: Process error %1: %2").arg(error).arg(m_gdbProc.errorString());
|
||||
logMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
const QString msg = exitStatus == QProcess::NormalExit ?
|
||||
QString::fromLatin1("GDB: Process finished (exit code: %1).").arg(exitCode) :
|
||||
QString::fromLatin1("GDB: Process crashed: %1").arg(m_gdbProc.errorString());
|
||||
if (state() == AdapterStarting) {
|
||||
emitDelayedAdapterStartFailed(msg);// Potentially emitted from QProcess::start() on Windows
|
||||
} else {
|
||||
logMessage(msg);
|
||||
setState(DebuggerNotReady);
|
||||
emit adapterShutDown();
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
logMessage(QString("GDB: Process Started"));
|
||||
maybeAdapterStarted();
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::maybeAdapterStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
|
||||
if (m_gdbProc.state() == QProcess::Running && m_trkDevice.isOpen()) {
|
||||
setState(AdapterStarted);
|
||||
emit adapterStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState)
|
||||
{
|
||||
logMessage(_("GDB: Process State %1").arg(newState));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::startAdapter()
|
||||
{
|
||||
// Retrieve parameters
|
||||
@@ -1634,13 +1576,12 @@ void TrkGdbAdapter::startAdapter()
|
||||
connect(m_gdbServer, SIGNAL(newConnection()),
|
||||
this, SLOT(handleGdbConnection()));
|
||||
|
||||
logMessage("STARTING GDB");
|
||||
logMessage(_("### Starting gdb %1").arg(m_options->gdb));
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
|
||||
gdbArgs.append(QLatin1String("-i"));
|
||||
gdbArgs.append(QLatin1String("mi"));
|
||||
m_gdbProc.start(m_options->gdb, gdbArgs);
|
||||
if (!m_engine->startGdb(gdbArgs, m_options->gdb)) {
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
waitForTrkConnect();
|
||||
}
|
||||
@@ -1701,8 +1642,7 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
|
||||
if (record.resultClass == GdbResultDone) {
|
||||
setState(InferiorRunningRequested);
|
||||
m_engine->postCommand(_("-exec-continue"), GdbEngine::RunRequest, CB(handleFirstContinue));
|
||||
emit inferiorPrepared();
|
||||
} else {
|
||||
QString msg = tr("Connecting to trk server adapter failed:\n")
|
||||
+ _(record.data.findChild("msg").data());
|
||||
@@ -1710,15 +1650,9 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleFirstContinue(const GdbResponse &record)
|
||||
void TrkGdbAdapter::startInferiorPhase2()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorRunning, qDebug() << state());
|
||||
if (record.resultClass == GdbResultDone) {
|
||||
debugMessage(_("INFERIOR STARTED"));
|
||||
showStatusMessage(msgInferiorRunning());
|
||||
} else {
|
||||
emit inferiorStartFailed(msgConnectRemoteServerFailed(record.toString()));
|
||||
}
|
||||
m_engine->continueInferiorInternal();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -1794,7 +1728,7 @@ void TrkGdbAdapter::write(const QByteArray &data)
|
||||
trkReadMemoryMessage(m_session.dataseg, 12));
|
||||
return;
|
||||
}
|
||||
m_gdbProc.write(data);
|
||||
m_engine->m_gdbProc.write(data);
|
||||
}
|
||||
|
||||
uint oldPC;
|
||||
@@ -1992,79 +1926,7 @@ void TrkGdbAdapter::cleanup()
|
||||
|
||||
void TrkGdbAdapter::shutdown()
|
||||
{
|
||||
switch (state()) {
|
||||
case AdapterStarting:
|
||||
case AdapterStartFailed:
|
||||
cleanup();
|
||||
setState(DebuggerNotReady);
|
||||
return;
|
||||
|
||||
case InferiorStopping:
|
||||
case InferiorRunningRequested:
|
||||
case InferiorRunning:
|
||||
//sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
|
||||
// Fall through.
|
||||
|
||||
case InferiorStopped:
|
||||
//sendTrkMessage(0x41, TrkCallback(), trkDeleteProcessMessage(), "Delete process");
|
||||
//sendTrkMessage(0x02, TrkCB(handleDisconnect));
|
||||
setState(InferiorShuttingDown);
|
||||
m_engine->postCommand(_("kill"), CB(handleKill));
|
||||
return;
|
||||
|
||||
case InferiorShutDown:
|
||||
setState(AdapterShuttingDown);
|
||||
cleanup();
|
||||
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
|
||||
return;
|
||||
|
||||
/*
|
||||
if (m_options->mode == TrkOptions::BlueTooth
|
||||
&& m_rfcommProc.state() == QProcess::Running)
|
||||
m_rfcommProc.kill();
|
||||
m_rfcommProc.terminate();
|
||||
m_rfcommProc.write(ba);
|
||||
m_rfcommProc.terminate();
|
||||
m_rfcommProc.waitForFinished();
|
||||
|
||||
m_gdbProc.kill();
|
||||
m_gdbProc.terminate();
|
||||
|
||||
QByteArray ba;
|
||||
ba.append(0x03);
|
||||
QProcess proc;
|
||||
proc.start("rfcomm release " + m_options->blueToothDevice);
|
||||
proc.waitForFinished();
|
||||
m_gdbProc.waitForFinished(msecs);
|
||||
*/
|
||||
|
||||
default:
|
||||
QTC_ASSERT(false, qDebug() << state());
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleKill(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
setState(InferiorShutDown);
|
||||
emit inferiorShutDown();
|
||||
shutdown(); // re-iterate...
|
||||
} else {
|
||||
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
|
||||
setState(InferiorShutdownFailed);
|
||||
emit inferiorShutdownFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleExit(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
qDebug() << "EXITED, NO MESSAGE...";
|
||||
// don't set state here, this will be handled in handleGdbFinished()
|
||||
} else {
|
||||
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
|
||||
emit adapterShutdownFailed(msg);
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -30,10 +30,11 @@
|
||||
#ifndef DEBUGGER_TRKGDBADAPTER_H
|
||||
#define DEBUGGER_TRKGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
|
||||
#include "trkutils.h"
|
||||
#include "trkdevice.h"
|
||||
#include "trkoptions.h"
|
||||
#include "abstractgdbadapter.h"
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QPointer>
|
||||
@@ -163,8 +164,6 @@ public:
|
||||
//
|
||||
void start(const QString &program, const QStringList &args,
|
||||
QIODevice::OpenMode mode = QIODevice::ReadWrite);
|
||||
QByteArray readAllStandardError();
|
||||
QByteArray readAllStandardOutput();
|
||||
void write(const QByteArray &data);
|
||||
bool isTrkAdapter() const { return true; }
|
||||
bool dumpersAvailable() const { return false; }
|
||||
@@ -172,19 +171,16 @@ public:
|
||||
private:
|
||||
void startAdapter();
|
||||
void startInferior();
|
||||
void startInferiorPhase2();
|
||||
void interruptInferior();
|
||||
void shutdown();
|
||||
|
||||
void cleanup();
|
||||
void emitDelayedAdapterStartFailed(const QString &msg);
|
||||
Q_SLOT void slotEmitDelayedAdapterStartFailed();
|
||||
void emitDelayedInferiorStartFailed(const QString &msg);
|
||||
Q_SLOT void slotEmitDelayedInferiorStartFailed();
|
||||
|
||||
Q_SLOT void waitForTrkConnect();
|
||||
void handleKill(const GdbResponse &response);
|
||||
void handleExit(const GdbResponse &response);
|
||||
void handleTargetRemote(const GdbResponse &response);
|
||||
void handleFirstContinue(const GdbResponse &response);
|
||||
|
||||
//
|
||||
// TRK
|
||||
@@ -285,13 +281,6 @@ private:
|
||||
bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
|
||||
void tryAnswerGdbMemoryRequest(bool buffered);
|
||||
|
||||
Q_SLOT void handleGdbError(QProcess::ProcessError error);
|
||||
Q_SLOT void handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
Q_SLOT void handleGdbStarted();
|
||||
Q_SLOT void handleGdbStateChanged(QProcess::ProcessState newState);
|
||||
|
||||
void maybeAdapterStarted();
|
||||
|
||||
void logMessage(const QString &msg); // triggers output() if m_verbose
|
||||
Q_SLOT void trkLogMessage(const QString &msg);
|
||||
|
||||
|
@@ -123,7 +123,7 @@ public:
|
||||
protected:
|
||||
void showStatusMessage(const QString &msg, int timeout = -1);
|
||||
DebuggerState state() const;
|
||||
void setState(DebuggerState state);
|
||||
void setState(DebuggerState state, bool forced = false);
|
||||
DebuggerManager *manager() const { return m_manager; }
|
||||
DebuggerManager *m_manager;
|
||||
|
||||
|
@@ -33,12 +33,17 @@
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QMetaType>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDebug;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
StackFrame();
|
||||
void clear();
|
||||
bool isUsable() const;
|
||||
QString toToolTip() const;
|
||||
QString toString() const;
|
||||
@@ -52,6 +57,8 @@ struct StackFrame
|
||||
QString address;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug d, const StackFrame &);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
@@ -37,12 +37,23 @@
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
StackFrame::StackFrame()
|
||||
: level(0), line(0)
|
||||
{}
|
||||
|
||||
void StackFrame::clear()
|
||||
{
|
||||
line = level = 0;
|
||||
function.clear();
|
||||
file.clear();
|
||||
from.clear();
|
||||
to.clear();
|
||||
address.clear();
|
||||
}
|
||||
|
||||
bool StackFrame::isUsable() const
|
||||
{
|
||||
return !file.isEmpty() && QFileInfo(file).isReadable();
|
||||
@@ -52,12 +63,12 @@ QString StackFrame::toString() const
|
||||
{
|
||||
QString res;
|
||||
QTextStream str(&res);
|
||||
str << StackHandler::tr("Address:") << " " << address << " "
|
||||
<< StackHandler::tr("Function:") << " " << function << " "
|
||||
<< StackHandler::tr("File:") << " " << file << " "
|
||||
<< StackHandler::tr("Line:") << " " << line << " "
|
||||
<< StackHandler::tr("From:") << " " << from << " "
|
||||
<< StackHandler::tr("To:") << " " << to;
|
||||
str << StackHandler::tr("Address:") << ' ' << address << ' '
|
||||
<< StackHandler::tr("Function:") << ' ' << function << ' '
|
||||
<< StackHandler::tr("File:") << ' ' << file << ' '
|
||||
<< StackHandler::tr("Line:") << ' ' << line << ' '
|
||||
<< StackHandler::tr("From:") << ' ' << from << ' '
|
||||
<< StackHandler::tr("To:") << ' ' << to;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -76,6 +87,23 @@ QString StackFrame::toToolTip() const
|
||||
return res;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const StackFrame &f)
|
||||
{
|
||||
QString res;
|
||||
QTextStream str(&res);
|
||||
str << "level=" << f.level << " address=" << f.address;
|
||||
if (!f.function.isEmpty())
|
||||
str << ' ' << f.function;
|
||||
if (!f.file.isEmpty())
|
||||
str << ' ' << f.file << ':' << f.line;
|
||||
if (!f.from.isEmpty())
|
||||
str << " from=" << f.from;
|
||||
if (!f.to.isEmpty())
|
||||
str << " to=" << f.to;
|
||||
d.nospace() << res;
|
||||
return d;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// StackHandler
|
||||
@@ -379,3 +407,5 @@ void ThreadsHandler::notifyRunning()
|
||||
it->notifyRunning();
|
||||
emit dataChanged(index(0, 1), index(m_threads.size()- 1, ColumnCount - 1));
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
@@ -30,18 +30,11 @@
|
||||
#include "threadswindow.h"
|
||||
|
||||
#include "debuggeractions.h"
|
||||
#include "stackhandler.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QContextMenuEvent>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QMenu>
|
||||
|
||||
using Debugger::Internal::ThreadsWindow;
|
||||
|
||||
@@ -63,46 +56,38 @@ ThreadsWindow::ThreadsWindow(QWidget *parent)
|
||||
this, SLOT(setAlternatingRowColorsHelper(bool)));
|
||||
}
|
||||
|
||||
void ThreadsWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
//QHeaderView *hv = header();
|
||||
//int totalSize = event->size().width() - 120;
|
||||
//hv->resizeSection(0, 45);
|
||||
//hv->resizeSection(1, totalSize);
|
||||
//hv->resizeSection(2, 55);
|
||||
QTreeView::resizeEvent(event);
|
||||
}
|
||||
|
||||
void ThreadsWindow::rowActivated(const QModelIndex &index)
|
||||
{
|
||||
//qDebug() << "ACTIVATED: " << index.row() << index.column();
|
||||
emit threadSelected(index.row());
|
||||
}
|
||||
|
||||
void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu menu;
|
||||
QAction *act1 = menu.addAction(tr("Adjust column widths to contents"));
|
||||
QAction *act2 = menu.addAction(tr("Always adjust column widths to contents"));
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
|
||||
QAction *adjustColumnAction = menu.addAction(tr("Adjust column widths to contents"));
|
||||
QAction *alwaysAdjustColumnAction = menu.addAction(tr("Always adjust column widths to contents"));
|
||||
alwaysAdjustColumnAction->setCheckable(true);
|
||||
alwaysAdjustColumnAction->setChecked(m_alwaysResizeColumnsToContents);
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(theDebuggerAction(SettingsDialog));
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
if(!act)
|
||||
return;
|
||||
|
||||
if (act == act1)
|
||||
if (act == adjustColumnAction) {
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
} else if (act == alwaysAdjustColumnAction) {
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadsWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
//resizeColumnToContents(1);
|
||||
const int columnCount = model()->columnCount();
|
||||
for (int c = 0 ; c < columnCount; c++)
|
||||
resizeColumnToContents(c);
|
||||
}
|
||||
|
||||
void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
@@ -111,6 +96,4 @@ void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
//header()->setResizeMode(1, mode);
|
||||
}
|
||||
|
||||
|
@@ -54,7 +54,6 @@ private slots:
|
||||
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
|
||||
|
||||
private:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
|
@@ -105,6 +105,7 @@ WatchData::WatchData() :
|
||||
generation(-1),
|
||||
valueEnabled(true),
|
||||
valueEditable(true),
|
||||
error(false),
|
||||
source(0),
|
||||
state(InitialState),
|
||||
changed(false)
|
||||
@@ -127,7 +128,8 @@ bool WatchData::isEqual(const WatchData &other) const
|
||||
&& framekey == other.framekey
|
||||
&& hasChildren == other.hasChildren
|
||||
&& valueEnabled == other.valueEnabled
|
||||
&& valueEditable == other.valueEditable;
|
||||
&& valueEditable == other.valueEditable
|
||||
&& error == other.error;
|
||||
}
|
||||
|
||||
void WatchData::setError(const QString &msg)
|
||||
@@ -137,6 +139,7 @@ void WatchData::setError(const QString &msg)
|
||||
setHasChildren(false);
|
||||
valueEnabled = false;
|
||||
valueEditable = false;
|
||||
error = true;
|
||||
}
|
||||
|
||||
void WatchData::setValue(const QString &value0)
|
||||
@@ -232,6 +235,8 @@ QString WatchData::toString() const
|
||||
str << "iname=\"" << iname << doubleQuoteComma;
|
||||
if (!name.isEmpty() && name != iname)
|
||||
str << "name=\"" << name << doubleQuoteComma;
|
||||
if (error)
|
||||
str << "error,";
|
||||
if (!addr.isEmpty())
|
||||
str << "addr=\"" << addr << doubleQuoteComma;
|
||||
if (!exp.isEmpty())
|
||||
@@ -310,6 +315,19 @@ QString WatchData::toToolTip() const
|
||||
return res;
|
||||
}
|
||||
|
||||
QString WatchData::msgNotInScope()
|
||||
{
|
||||
static const QString rc = QCoreApplication::translate("Debugger::Internal::WatchData", "<not in scope>");
|
||||
return rc;
|
||||
}
|
||||
|
||||
QString WatchData::shadowedName(const QString &name, int seen)
|
||||
{
|
||||
if (seen <= 0)
|
||||
return name;
|
||||
return QCoreApplication::translate("Debugger::Internal::WatchData", "%1 <shadowed %2>").arg(name).arg(seen);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WatchModel
|
||||
@@ -590,9 +608,10 @@ void WatchModel::fetchMore(const QModelIndex &index)
|
||||
QTC_ASSERT(index.isValid(), return);
|
||||
QTC_ASSERT(!watchItem(index)->fetchTriggered, return);
|
||||
if (WatchItem *item = watchItem(index)) {
|
||||
m_handler->m_expandedINames.insert(item->iname);
|
||||
item->fetchTriggered = true;
|
||||
WatchData data = *item;
|
||||
if (item->children.isEmpty()) {
|
||||
WatchData data = *item;
|
||||
data.setChildrenNeeded();
|
||||
m_handler->m_manager->updateWatchData(data);
|
||||
}
|
||||
@@ -771,10 +790,13 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
|
||||
{
|
||||
WatchItem &data = *watchItem(index);
|
||||
if (role == ExpandedRole) {
|
||||
if (value.toBool())
|
||||
if (value.toBool()) {
|
||||
// Should already have been triggered by fetchMore()
|
||||
QTC_ASSERT(m_handler->m_expandedINames.contains(data.iname), /**/);
|
||||
m_handler->m_expandedINames.insert(data.iname);
|
||||
else
|
||||
} else {
|
||||
m_handler->m_expandedINames.remove(data.iname);
|
||||
}
|
||||
} else if (role == TypeFormatRole) {
|
||||
m_handler->setFormat(data.type, value.toInt());
|
||||
} else if (role == IndividualFormatRole) {
|
||||
|
@@ -117,6 +117,9 @@ public:
|
||||
|
||||
bool isEqual(const WatchData &other) const;
|
||||
|
||||
static QString msgNotInScope();
|
||||
static QString shadowedName(const QString &name, int seen);
|
||||
|
||||
public:
|
||||
QString iname; // internal name sth like 'local.baz.public.a'
|
||||
QString exp; // the expression
|
||||
@@ -135,6 +138,7 @@ public:
|
||||
int generation; // when updated?
|
||||
bool valueEnabled; // value will be greyed out or not
|
||||
bool valueEditable; // value will be editable
|
||||
bool error;
|
||||
|
||||
private:
|
||||
|
||||
|
@@ -43,6 +43,9 @@
|
||||
#include <cpptools/cpptoolsconstants.h>
|
||||
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <cplusplus/Overview.h>
|
||||
#include <Symbols.h>
|
||||
#include <Scope.h>
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
@@ -51,6 +54,7 @@
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <QtCore/QHash>
|
||||
|
||||
#include <QtGui/QTextCursor>
|
||||
#include <QtGui/QPlainTextEdit>
|
||||
@@ -59,6 +63,78 @@
|
||||
#include <ctype.h>
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
// Debug helpers for code model. @todo: Move to some CppTools library?
|
||||
namespace CPlusPlus {
|
||||
|
||||
static void debugCppSymbolRecursion(QTextStream &str, const Overview &o,
|
||||
const Symbol &s, bool doRecurse = true,
|
||||
int recursion = 0)
|
||||
{
|
||||
for (int i = 0; i < recursion; i++)
|
||||
str << " ";
|
||||
str << "Symbol: " << o.prettyName(s.name()) << " at line " << s.line();
|
||||
if (s.isFunction())
|
||||
str << " function";
|
||||
if (s.isClass())
|
||||
str << " class";
|
||||
if (s.isDeclaration())
|
||||
str << " declaration";
|
||||
if (s.isBlock())
|
||||
str << " block";
|
||||
if (doRecurse && s.isScopedSymbol()) {
|
||||
const ScopedSymbol *scoped = s.asScopedSymbol();
|
||||
const int size = scoped->memberCount();
|
||||
str << " scoped symbol of " << size << '\n';
|
||||
for (int m = 0; m < size; m++)
|
||||
debugCppSymbolRecursion(str, o, *scoped->memberAt(m), true, recursion + 1);
|
||||
} else {
|
||||
str << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const Symbol &s)
|
||||
{
|
||||
QString output;
|
||||
CPlusPlus::Overview o;
|
||||
QTextStream str(&output);
|
||||
debugCppSymbolRecursion(str, o, s, true, 0);
|
||||
d.nospace() << output;
|
||||
return d;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug d, const Scope &scope)
|
||||
{
|
||||
QString output;
|
||||
Overview o;
|
||||
QTextStream str(&output);
|
||||
const int size = scope.symbolCount();
|
||||
str << "Scope of " << size;
|
||||
if (scope.isNamespaceScope())
|
||||
str << " namespace";
|
||||
if (scope.isClassScope())
|
||||
str << " class";
|
||||
if (scope.isEnumScope())
|
||||
str << " enum";
|
||||
if (scope.isBlockScope())
|
||||
str << " block";
|
||||
if (scope.isFunctionScope())
|
||||
str << " function";
|
||||
if (scope.isPrototypeScope())
|
||||
str << " prototype";
|
||||
if (const Symbol *owner = scope.owner()) {
|
||||
str << " owner: ";
|
||||
debugCppSymbolRecursion(str, o, *owner, false, 0);
|
||||
} else {
|
||||
str << " 0-owner\n";
|
||||
}
|
||||
for (int s = 0; s < size; s++)
|
||||
debugCppSymbolRecursion(str, o, *scope.symbolAt(s), true, 2);
|
||||
d.nospace() << output;
|
||||
return d;
|
||||
}
|
||||
} // namespace CPlusPlus
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -217,6 +293,135 @@ QString stripPointerType(QString type)
|
||||
return type;
|
||||
}
|
||||
|
||||
/* getUninitializedVariables(): Get variables that are not initialized
|
||||
* at a certain line of a function from the code model to be able to
|
||||
* indicate them as not in scope in the locals view.
|
||||
* Find document + function in the code model, do a double check and
|
||||
* collect declarative symbols that are in the function past or on
|
||||
* the current line. blockRecursion() recurses up the scopes
|
||||
* and collect symbols declared past or on the current line.
|
||||
* Recursion goes up from the innermost scope, keeping a map
|
||||
* of occurrences seen, to be able to derive the names of
|
||||
* shadowed variables as the debugger sees them:
|
||||
\code
|
||||
int x; // Occurrence (1), should be reported as "x <shadowed 1>"
|
||||
if (true) {
|
||||
int x = 5; (2) // Occurrence (2), should be reported as "x"
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
typedef QHash<QString, int> SeenHash;
|
||||
|
||||
static void blockRecursion(const CPlusPlus::Overview &overview,
|
||||
const CPlusPlus::Scope *scope,
|
||||
unsigned line,
|
||||
QStringList *uninitializedVariables,
|
||||
SeenHash *seenHash,
|
||||
int level = 0)
|
||||
{
|
||||
const int size = scope->symbolCount();
|
||||
for (int s = 0; s < size; s++){
|
||||
const CPlusPlus::Symbol *symbol = scope->symbolAt(s);
|
||||
if (symbol->isDeclaration()) {
|
||||
// Find out about shadowed symbols by bookkeeping
|
||||
// the already seen occurrences in a hash.
|
||||
const QString name = overview.prettyName(symbol->name());
|
||||
SeenHash::iterator it = seenHash->find(name);
|
||||
if (it == seenHash->end()) {
|
||||
it = seenHash->insert(name, 0);
|
||||
} else {
|
||||
++(it.value());
|
||||
}
|
||||
// Is the declaration on or past the current line, that is,
|
||||
// the variable not initialized.
|
||||
if (symbol->line() >= line)
|
||||
uninitializedVariables->push_back(WatchData::shadowedName(name, it.value()));
|
||||
}
|
||||
}
|
||||
// Next block scope.
|
||||
if (const CPlusPlus::Scope *enclosingScope = scope->enclosingBlockScope())
|
||||
blockRecursion(overview, enclosingScope, line, uninitializedVariables, seenHash, level + 1);
|
||||
}
|
||||
|
||||
// Inline helper with integer error return codes.
|
||||
static inline
|
||||
int getUninitializedVariablesI(const CPlusPlus::Snapshot &snapshot,
|
||||
const QString &functionName,
|
||||
const QString &file,
|
||||
int line,
|
||||
QStringList *uninitializedVariables)
|
||||
{
|
||||
uninitializedVariables->clear();
|
||||
// Find document
|
||||
if (snapshot.empty() || functionName.isEmpty() || file.isEmpty() || line < 1)
|
||||
return 1;
|
||||
const CPlusPlus::Snapshot::ConstIterator docIt = snapshot.constFind(file);
|
||||
if (docIt == snapshot.constEnd())
|
||||
return 2;
|
||||
const CPlusPlus::Document::Ptr doc = docIt.value();
|
||||
// Look at symbol at line and find its function. Either it is the
|
||||
// function itself or some expression/variable.
|
||||
const CPlusPlus::Symbol *symbolAtLine = doc->findSymbolAt(line, 0);
|
||||
if (!symbolAtLine)
|
||||
return 4;
|
||||
// First figure out the function to do a safety name check
|
||||
// and the innermost scope at cursor position
|
||||
const CPlusPlus::Function *function = 0;
|
||||
const CPlusPlus::Scope *innerMostScope = 0;
|
||||
if (symbolAtLine->isFunction()) {
|
||||
function = symbolAtLine->asFunction();
|
||||
if (function->memberCount() == 1) // Skip over function block
|
||||
if (CPlusPlus::Block *block = function->memberAt(0)->asBlock())
|
||||
innerMostScope = block->members();
|
||||
} else {
|
||||
if (const CPlusPlus::Scope *functionScope = symbolAtLine->enclosingFunctionScope()) {
|
||||
function = functionScope->owner()->asFunction();
|
||||
innerMostScope = symbolAtLine->isBlock() ?
|
||||
symbolAtLine->asBlock()->members() :
|
||||
symbolAtLine->enclosingBlockScope();
|
||||
}
|
||||
}
|
||||
if (!function || !innerMostScope)
|
||||
return 7;
|
||||
// Compare function names with a bit off fuzz,
|
||||
// skipping modules from a CDB symbol "lib!foo" or namespaces
|
||||
// that the code model does not show at this point
|
||||
CPlusPlus::Overview overview;
|
||||
const QString name = overview.prettyName(function->name());
|
||||
if (!functionName.endsWith(name))
|
||||
return 11;
|
||||
if (functionName.size() > name.size()) {
|
||||
const char previousChar = functionName.at(functionName.size() - name.size() - 1).toLatin1();
|
||||
if (previousChar != ':' && previousChar != '!' )
|
||||
return 11;
|
||||
}
|
||||
// Starting from the innermost block scope, collect declarations.
|
||||
SeenHash seenHash;
|
||||
blockRecursion(overview, innerMostScope, line, uninitializedVariables, &seenHash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
|
||||
const QString &function,
|
||||
const QString &file,
|
||||
int line,
|
||||
QStringList *uninitializedVariables)
|
||||
{
|
||||
const int rc = getUninitializedVariablesI(snapshot, function, file, line, uninitializedVariables);
|
||||
if (debug) {
|
||||
QString msg;
|
||||
QTextStream str(&msg);
|
||||
str << "getUninitializedVariables() " << function << ' ' << file << ':' << line
|
||||
<< " returns (int) " << rc << " '"
|
||||
<< uninitializedVariables->join(QString(QLatin1Char(','))) << '\'';
|
||||
if (rc)
|
||||
str << " of " << snapshot.keys().size() << " documents";
|
||||
qDebug() << msg;
|
||||
}
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
QString gdbQuoteTypes(const QString &type)
|
||||
{
|
||||
// gdb does not understand sizeof(Core::IFile*).
|
||||
|
@@ -45,6 +45,10 @@ namespace Core {
|
||||
class IEditor;
|
||||
}
|
||||
|
||||
namespace CPlusPlus {
|
||||
class Snapshot;
|
||||
}
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -89,6 +93,15 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
|
||||
// Decode string data as returned by the dumper helpers.
|
||||
QString decodeData(const QByteArray &baIn, int encoding);
|
||||
|
||||
// Get variables that are not initialized at a certain line
|
||||
// of a function from the code model. Shadowed variables will
|
||||
// be reported using the debugger naming conventions '<shadowed n>'
|
||||
bool getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
|
||||
const QString &function,
|
||||
const QString &file,
|
||||
int line,
|
||||
QStringList *uninitializedVariables);
|
||||
|
||||
/* Attempt to put common code of the dumper handling into a helper
|
||||
* class.
|
||||
* "Custom dumper" is a library compiled against the current
|
||||
|
@@ -136,10 +136,10 @@ WatchWindow::WatchWindow(Type type, DebuggerManager *manager, QWidget *parent)
|
||||
|
||||
connect(act, SIGNAL(toggled(bool)),
|
||||
this, SLOT(setAlternatingRowColorsHelper(bool)));
|
||||
connect(this, SIGNAL(expanded(QModelIndex)),
|
||||
this, SLOT(expandNode(QModelIndex)));
|
||||
connect(this, SIGNAL(collapsed(QModelIndex)),
|
||||
this, SLOT(collapseNode(QModelIndex)));
|
||||
connect(this, SIGNAL(expanded(QModelIndex)),
|
||||
this, SLOT(expandNode(QModelIndex)));
|
||||
connect(this, SIGNAL(collapsed(QModelIndex)),
|
||||
this, SLOT(collapseNode(QModelIndex)));
|
||||
}
|
||||
|
||||
void WatchWindow::expandNode(const QModelIndex &idx)
|
||||
@@ -253,10 +253,11 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
QAction *actInsertNewWatchItem = menu.addAction(tr("Insert new watch item"));
|
||||
QAction *actSelectWidgetToWatch = menu.addAction(tr("Select widget to watch"));
|
||||
|
||||
const bool actionsEnabled = m_manager->debuggerActionsEnabled();
|
||||
const QString address = model()->data(mi0, AddressRole).toString();
|
||||
QAction *actWatchKnownMemory = 0;
|
||||
QAction *actWatchUnknownMemory = new QAction(tr("Open memory editor..."), &menu);
|
||||
actWatchUnknownMemory->setEnabled(m_manager->debuggerActionsEnabled());
|
||||
actWatchUnknownMemory->setEnabled(actionsEnabled);
|
||||
|
||||
if (!address.isEmpty())
|
||||
actWatchKnownMemory = new QAction(tr("Open memory editor at %1").arg(address), &menu);
|
||||
@@ -276,7 +277,9 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
|
||||
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
||||
menu.addAction(theDebuggerAction(UseDebuggingHelpers));
|
||||
|
||||
QAction *actClearCodeModelSnapshot = new QAction(tr("Refresh code model snapshot"), &menu);
|
||||
actClearCodeModelSnapshot->setEnabled(actionsEnabled && theDebuggerAction(UseCodeModel)->isChecked());
|
||||
menu.addAction(actClearCodeModelSnapshot);
|
||||
menu.addSeparator();
|
||||
menu.addAction(theDebuggerAction(UseToolTipsInLocalsView));
|
||||
|
||||
@@ -311,6 +314,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
} else if (act == actSelectWidgetToWatch) {
|
||||
grabMouse(Qt::CrossCursor);
|
||||
m_grabbing = true;
|
||||
} else if (act == actClearCodeModelSnapshot) {
|
||||
m_manager->clearCppCodeModelSnapshot();
|
||||
} else {
|
||||
for (int i = 0; i != alternativeFormats.size(); ++i) {
|
||||
if (act == typeFormatActions.at(i))
|
||||
|
@@ -670,6 +670,7 @@ void S60DeviceRunControlBase::signsisProcessFinished()
|
||||
}
|
||||
m_launcher = new trk::Launcher();
|
||||
connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished()));
|
||||
connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(printConnectFailed(QString)));
|
||||
connect(m_launcher, SIGNAL(copyingStarted()), this, SLOT(printCopyingNotice()));
|
||||
connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(printCreateFileFailed(QString,QString)));
|
||||
connect(m_launcher, SIGNAL(canNotWriteFile(QString,QString)), this, SLOT(printWriteFileFailed(QString,QString)));
|
||||
@@ -713,6 +714,11 @@ void S60DeviceRunControlBase::printCloseFileFailed(const QString &filename, cons
|
||||
emit addToOutputWindow(this, msg.arg(filename, errorMessage));
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::printConnectFailed(const QString &errorMessage)
|
||||
{
|
||||
emit addToOutputWindow(this, tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage));
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::printCopyingNotice()
|
||||
{
|
||||
emit addToOutputWindow(this, tr("Copying install file..."));
|
||||
|
@@ -180,6 +180,7 @@ private slots:
|
||||
void makesisProcessFinished();
|
||||
void signsisProcessFailed();
|
||||
void signsisProcessFinished();
|
||||
void printConnectFailed(const QString &errorMessage);
|
||||
void printCopyingNotice();
|
||||
void printCreateFileFailed(const QString &filename, const QString &errorMessage);
|
||||
void printWriteFileFailed(const QString &filename, const QString &errorMessage);
|
||||
|
@@ -54,7 +54,7 @@
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
AST::AST()
|
||||
{ }
|
||||
@@ -2493,4 +2493,4 @@ unsigned ObjCSynchronizedStatementAST::lastToken() const
|
||||
return synchronized_token + 1;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include "ASTfwd.h"
|
||||
#include "MemoryPool.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
template <typename _Tp>
|
||||
class List: public Managed
|
||||
@@ -3168,7 +3168,7 @@ protected:
|
||||
virtual void accept0(ASTVisitor *visitor);
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_AST_H
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "AST.h"
|
||||
#include "ASTVisitor.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
@@ -986,7 +986,9 @@ SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
|
||||
// copy ExpressionAST
|
||||
// copy SizeofExpressionAST
|
||||
ast->sizeof_token = sizeof_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
if (expression) ast->expression = expression->clone(pool);
|
||||
ast->rparen_token = rparen_token;
|
||||
return ast;
|
||||
}
|
||||
|
||||
@@ -1207,7 +1209,7 @@ IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
IdentifierListAST *ast = new (pool) IdentifierListAST;
|
||||
// copy IdentifierListAST
|
||||
if (ast->name) ast->name = name->clone(pool);
|
||||
if (name) ast->name = name->clone(pool);
|
||||
ast->comma_token = comma_token;
|
||||
if (next) ast->next = next->clone(pool);
|
||||
return ast;
|
||||
@@ -1249,9 +1251,11 @@ ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const
|
||||
ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCProtocolForwardDeclarationAST *ast = new (pool) ObjCProtocolForwardDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCProtocolForwardDeclarationAST
|
||||
if (attributes) ast->attributes = attributes->clone(pool);
|
||||
ast->protocol_token = protocol_token;
|
||||
if (identifier_list) ast->identifier_list = identifier_list;
|
||||
if (identifier_list) ast->identifier_list = identifier_list->clone(pool);
|
||||
ast->semicolon_token = semicolon_token;
|
||||
return ast;
|
||||
}
|
||||
@@ -1259,6 +1263,8 @@ ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclarationAST::clone(Memo
|
||||
ObjCProtocolDeclarationAST *ObjCProtocolDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCProtocolDeclarationAST *ast = new (pool) ObjCProtocolDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCProtocolDeclarationAST
|
||||
if (attributes) ast->attributes = attributes->clone(pool);
|
||||
ast->protocol_token = protocol_token;
|
||||
if (name) ast->name = name->clone(pool);
|
||||
@@ -1271,15 +1277,35 @@ ObjCProtocolDeclarationAST *ObjCProtocolDeclarationAST::clone(MemoryPool *pool)
|
||||
ObjCProtocolRefsAST *ObjCProtocolRefsAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCProtocolRefsAST *ast = new (pool) ObjCProtocolRefsAST;
|
||||
// copy ObjCProtocolRefsAST
|
||||
ast->less_token = less_token;
|
||||
if (ast->identifier_list) ast->identifier_list = identifier_list->clone(pool);
|
||||
if (identifier_list) ast->identifier_list = identifier_list->clone(pool);
|
||||
ast->greater_token = greater_token;
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCMessageArgumentAST *ObjCMessageArgumentAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageArgumentAST *ast = new (pool) ObjCMessageArgumentAST;
|
||||
// copy ObjCMessageArgumentAST
|
||||
if (parameter_value_expression) ast->parameter_value_expression = parameter_value_expression->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCMessageArgumentListAST *ObjCMessageArgumentListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageArgumentListAST *ast = new (pool) ObjCMessageArgumentListAST;
|
||||
// copy ObjCMessageArgumentListAST
|
||||
if (arg) ast->arg = arg->clone(pool);
|
||||
if (next) ast->next = next->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCMessageExpressionAST *ObjCMessageExpressionAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageExpressionAST *ast = new (pool) ObjCMessageExpressionAST;
|
||||
// copy ExpressionAST
|
||||
// copy ObjCMessageExpressionAST
|
||||
ast->lbracket_token = lbracket_token;
|
||||
if (receiver_expression) ast->receiver_expression = receiver_expression->clone(pool);
|
||||
if (selector) ast->selector = selector->clone(pool);
|
||||
@@ -1288,24 +1314,11 @@ ObjCMessageExpressionAST *ObjCMessageExpressionAST::clone(MemoryPool *pool) cons
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCMessageArgumentListAST *ObjCMessageArgumentListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageArgumentListAST *ast = new (pool) ObjCMessageArgumentListAST;
|
||||
if (arg) ast->arg = arg->clone(pool);
|
||||
if (next) ast->next = next->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCMessageArgumentAST *ObjCMessageArgumentAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageArgumentAST *ast = new (pool) ObjCMessageArgumentAST;
|
||||
if (parameter_value_expression) ast->parameter_value_expression = parameter_value_expression->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCProtocolExpressionAST *ObjCProtocolExpressionAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCProtocolExpressionAST *ast = new (pool) ObjCProtocolExpressionAST;
|
||||
// copy ExpressionAST
|
||||
// copy ObjCProtocolExpressionAST
|
||||
ast->protocol_token = protocol_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
ast->identifier_token = identifier_token;
|
||||
@@ -1316,8 +1329,8 @@ ObjCProtocolExpressionAST *ObjCProtocolExpressionAST::clone(MemoryPool *pool) co
|
||||
ObjCTypeNameAST *ObjCTypeNameAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCTypeNameAST *ast = new (pool) ObjCTypeNameAST;
|
||||
// copy ObjCTypeNameAST
|
||||
ast->lparen_token = lparen_token;
|
||||
ast->type_qualifier = type_qualifier;
|
||||
if (type_id) ast->type_id = type_id->clone(pool);
|
||||
ast->rparen_token = rparen_token;
|
||||
return ast;
|
||||
@@ -1326,6 +1339,8 @@ ObjCTypeNameAST *ObjCTypeNameAST::clone(MemoryPool *pool) const
|
||||
ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCEncodeExpressionAST *ast = new (pool) ObjCEncodeExpressionAST;
|
||||
// copy ExpressionAST
|
||||
// copy ObjCEncodeExpressionAST
|
||||
ast->encode_token = encode_token;
|
||||
if (type_name) ast->type_name = type_name->clone(pool);
|
||||
return ast;
|
||||
@@ -1334,6 +1349,8 @@ ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
|
||||
ObjCSelectorWithoutArgumentsAST *ObjCSelectorWithoutArgumentsAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSelectorWithoutArgumentsAST *ast = new (pool) ObjCSelectorWithoutArgumentsAST;
|
||||
// copy ObjCSelectorAST
|
||||
// copy ObjCSelectorWithoutArgumentsAST
|
||||
ast->name_token = name_token;
|
||||
return ast;
|
||||
}
|
||||
@@ -1341,6 +1358,7 @@ ObjCSelectorWithoutArgumentsAST *ObjCSelectorWithoutArgumentsAST::clone(MemoryPo
|
||||
ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSelectorArgumentAST *ast = new (pool) ObjCSelectorArgumentAST;
|
||||
// copy ObjCSelectorArgumentAST
|
||||
ast->name_token = name_token;
|
||||
ast->colon_token = colon_token;
|
||||
return ast;
|
||||
@@ -1349,6 +1367,7 @@ ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const
|
||||
ObjCSelectorArgumentListAST *ObjCSelectorArgumentListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSelectorArgumentListAST *ast = new (pool) ObjCSelectorArgumentListAST;
|
||||
// copy ObjCSelectorArgumentListAST
|
||||
if (argument) ast->argument = argument->clone(pool);
|
||||
if (next) ast->next = next->clone(pool);
|
||||
return ast;
|
||||
@@ -1357,6 +1376,8 @@ ObjCSelectorArgumentListAST *ObjCSelectorArgumentListAST::clone(MemoryPool *pool
|
||||
ObjCSelectorWithArgumentsAST *ObjCSelectorWithArgumentsAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSelectorWithArgumentsAST *ast = new (pool) ObjCSelectorWithArgumentsAST;
|
||||
// copy ObjCSelectorAST
|
||||
// copy ObjCSelectorWithArgumentsAST
|
||||
if (selector_arguments) ast->selector_arguments = selector_arguments->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
@@ -1364,6 +1385,8 @@ ObjCSelectorWithArgumentsAST *ObjCSelectorWithArgumentsAST::clone(MemoryPool *po
|
||||
ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSelectorExpressionAST *ast = new (pool) ObjCSelectorExpressionAST;
|
||||
// copy ExpressionAST
|
||||
// copy ObjCSelectorExpressionAST
|
||||
ast->selector_token = selector_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
if (selector) ast->selector = selector->clone(pool);
|
||||
@@ -1374,6 +1397,7 @@ ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) co
|
||||
ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCInstanceVariablesDeclarationAST *ast = new (pool) ObjCInstanceVariablesDeclarationAST;
|
||||
// copy ObjCInstanceVariablesDeclarationAST
|
||||
ast->lbrace_token = lbrace_token;
|
||||
if (instance_variables) ast->instance_variables = instance_variables->clone(pool);
|
||||
ast->rbrace_token = rbrace_token;
|
||||
@@ -1383,6 +1407,8 @@ ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(
|
||||
ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCVisibilityDeclarationAST *ast = new (pool) ObjCVisibilityDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCVisibilityDeclarationAST
|
||||
ast->visibility_token = visibility_token;
|
||||
return ast;
|
||||
}
|
||||
@@ -1390,6 +1416,7 @@ ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *po
|
||||
ObjCPropertyAttributeAST *ObjCPropertyAttributeAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCPropertyAttributeAST *ast = new (pool) ObjCPropertyAttributeAST;
|
||||
// copy ObjCPropertyAttributeAST
|
||||
ast->attribute_identifier_token = attribute_identifier_token;
|
||||
ast->equals_token = equals_token;
|
||||
if (method_selector) ast->method_selector = method_selector->clone(pool);
|
||||
@@ -1399,6 +1426,7 @@ ObjCPropertyAttributeAST *ObjCPropertyAttributeAST::clone(MemoryPool *pool) cons
|
||||
ObjCPropertyAttributeListAST *ObjCPropertyAttributeListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCPropertyAttributeListAST *ast = new (pool) ObjCPropertyAttributeListAST;
|
||||
// copy ObjCPropertyAttributeListAST
|
||||
if (attr) ast->attr = attr->clone(pool);
|
||||
ast->comma_token = comma_token;
|
||||
if (next) ast->next = next->clone(pool);
|
||||
@@ -1408,6 +1436,8 @@ ObjCPropertyAttributeListAST *ObjCPropertyAttributeListAST::clone(MemoryPool *po
|
||||
ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCPropertyDeclarationAST *ast = new (pool) ObjCPropertyDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCPropertyDeclarationAST
|
||||
if (attributes) ast->attributes = attributes->clone(pool);
|
||||
ast->property_token = property_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
@@ -1420,6 +1450,9 @@ ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool)
|
||||
ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageArgumentDeclarationAST *ast = new (pool) ObjCMessageArgumentDeclarationAST;
|
||||
// copy ExpressionAST
|
||||
// copy NameAST
|
||||
// copy ObjCMessageArgumentDeclarationAST
|
||||
if (type_name) ast->type_name = type_name->clone(pool);
|
||||
if (attributes) ast->attributes = attributes->clone(pool);
|
||||
ast->param_name_token = param_name_token;
|
||||
@@ -1429,6 +1462,7 @@ ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(Memo
|
||||
ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMessageArgumentDeclarationListAST *ast = new (pool) ObjCMessageArgumentDeclarationListAST;
|
||||
// copy ObjCMessageArgumentDeclarationListAST
|
||||
if (argument_declaration) ast->argument_declaration = argument_declaration->clone(pool);
|
||||
if (next) ast->next = next->clone(pool);
|
||||
return ast;
|
||||
@@ -1437,9 +1471,12 @@ ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationListAST::cl
|
||||
ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMethodPrototypeAST *ast = new (pool) ObjCMethodPrototypeAST;
|
||||
// copy ObjCMethodPrototypeAST
|
||||
ast->method_type_token = method_type_token;
|
||||
if (type_name) ast->type_name = type_name->clone(pool);
|
||||
if (selector) ast->selector = selector->clone(pool);
|
||||
if (arguments) ast->arguments = arguments->clone(pool);
|
||||
ast->dot_dot_dot_token = dot_dot_dot_token;
|
||||
if (attributes) ast->attributes = attributes->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
@@ -1447,6 +1484,8 @@ ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
|
||||
ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCMethodDeclarationAST *ast = new (pool) ObjCMethodDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCMethodDeclarationAST
|
||||
if (method_prototype) ast->method_prototype = method_prototype->clone(pool);
|
||||
if (function_body) ast->function_body = function_body->clone(pool);
|
||||
ast->semicolon_token = semicolon_token;
|
||||
@@ -1456,15 +1495,15 @@ ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) cons
|
||||
ObjCSynthesizedPropertyAST *ObjCSynthesizedPropertyAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSynthesizedPropertyAST *ast = new (pool) ObjCSynthesizedPropertyAST;
|
||||
ast->property_identifier = property_identifier;
|
||||
// copy ObjCSynthesizedPropertyAST
|
||||
ast->equals_token = equals_token;
|
||||
ast->property_alias_identifier = property_alias_identifier;
|
||||
return ast;
|
||||
}
|
||||
|
||||
ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyListAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSynthesizedPropertyListAST *ast = new (pool) ObjCSynthesizedPropertyListAST;
|
||||
// copy ObjCSynthesizedPropertyListAST
|
||||
if (synthesized_property) ast->synthesized_property = synthesized_property->clone(pool);
|
||||
ast->comma_token = comma_token;
|
||||
if (next) ast->next = next->clone(pool);
|
||||
@@ -1474,6 +1513,8 @@ ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyListAST::clone(MemoryPool
|
||||
ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSynthesizedPropertiesDeclarationAST *ast = new (pool) ObjCSynthesizedPropertiesDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCSynthesizedPropertiesDeclarationAST
|
||||
ast->synthesized_token = synthesized_token;
|
||||
if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool);
|
||||
ast->semicolon_token = semicolon_token;
|
||||
@@ -1483,6 +1524,8 @@ ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST
|
||||
ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCDynamicPropertiesDeclarationAST *ast = new (pool) ObjCDynamicPropertiesDeclarationAST;
|
||||
// copy DeclarationAST
|
||||
// copy ObjCDynamicPropertiesDeclarationAST
|
||||
ast->dynamic_token = dynamic_token;
|
||||
if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool);
|
||||
ast->semicolon_token = semicolon_token;
|
||||
@@ -1492,6 +1535,8 @@ ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(
|
||||
ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCFastEnumerationAST *ast = new (pool) ObjCFastEnumerationAST;
|
||||
// copy StatementAST
|
||||
// copy ObjCFastEnumerationAST
|
||||
ast->for_token = for_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
if (type_specifiers) ast->type_specifiers = type_specifiers->clone(pool);
|
||||
@@ -1507,6 +1552,8 @@ ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const
|
||||
ObjCSynchronizedStatementAST *ObjCSynchronizedStatementAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
ObjCSynchronizedStatementAST *ast = new (pool) ObjCSynchronizedStatementAST;
|
||||
// copy StatementAST
|
||||
// copy ObjCSynchronizedStatementAST
|
||||
ast->synchronized_token = synchronized_token;
|
||||
ast->lparen_token = lparen_token;
|
||||
if (synchronized_object) ast->synchronized_object = synchronized_object->clone(pool);
|
||||
@@ -1514,6 +1561,3 @@ ObjCSynchronizedStatementAST *ObjCSynchronizedStatementAST::clone(MemoryPool *po
|
||||
if (statement) ast->statement = statement->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "AST.h"
|
||||
#include "ASTVisitor.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
void SimpleSpecifierAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
@@ -1465,4 +1465,4 @@ void ObjCSynchronizedStatementAST::accept0(ASTVisitor *visitor)
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -51,7 +51,7 @@
|
||||
#include "TranslationUnit.h"
|
||||
#include "Control.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
ASTVisitor::ASTVisitor(Control *control)
|
||||
: _control(control)
|
||||
@@ -111,4 +111,4 @@ void ASTVisitor::getTokenStartPosition(unsigned index, unsigned *line, unsigned
|
||||
void ASTVisitor::getTokenEndPosition(unsigned index, unsigned *line, unsigned *column) const
|
||||
{ getPosition(tokenAt(index).end(), line, column); }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "ASTfwd.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT ASTVisitor
|
||||
{
|
||||
@@ -371,7 +371,7 @@ private:
|
||||
Control *_control;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_ASTVISITOR_H
|
||||
|
@@ -51,8 +51,8 @@
|
||||
|
||||
#include <CPlusPlusForwardDeclarations.h>
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class AST;
|
||||
class ASTVisitor;
|
||||
@@ -203,7 +203,7 @@ class ObjCDynamicPropertiesDeclarationAST;
|
||||
class ObjCFastEnumerationAST;
|
||||
class ObjCSynchronizedStatementAST;
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_ASTFWD_H
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
template <typename _Tp, int SEGMENT_SHIFT = 4>
|
||||
class Array
|
||||
@@ -125,7 +125,7 @@ private:
|
||||
int _count;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_ARRAY_H
|
||||
|
@@ -49,34 +49,19 @@
|
||||
#ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
|
||||
#define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
|
||||
|
||||
#ifndef CPLUSPLUS_WITH_NO_QT
|
||||
#ifndef CPLUSPLUS_WITHOUT_QT
|
||||
# include <QtCore/qglobal.h>
|
||||
# define CPLUSPLUS_BEGIN_HEADER
|
||||
# define CPLUSPLUS_END_HEADER
|
||||
|
||||
# if defined(CPLUSPLUS_BUILD_LIB)
|
||||
# define CPLUSPLUS_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define CPLUSPLUS_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# define CPLUSPLUS_WITH_NAMESPACE
|
||||
#else
|
||||
# define CPLUSPLUS_BEGIN_HEADER
|
||||
# define CPLUSPLUS_END_HEADER
|
||||
# define CPLUSPLUS_EXPORT
|
||||
#endif
|
||||
|
||||
#ifdef CPLUSPLUS_WITH_NAMESPACE
|
||||
# define CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
|
||||
# define CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPLus
|
||||
# define CPLUSPLUS_USE_NAMESPACE using namespace CPlusPlus;
|
||||
#else
|
||||
# define CPLUSPLUS_BEGIN_NAMESPACE
|
||||
# define CPLUSPLUS_END_NAMESPACE
|
||||
# define CPLUSPLUS_USE_NAMESPACE ;
|
||||
#endif
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
namespace CPlusPlus {
|
||||
|
||||
class TranslationUnit;
|
||||
class Semantic;
|
||||
@@ -144,7 +129,6 @@ class ObjCProtocol;
|
||||
class ObjCForwardProtocolDeclaration;
|
||||
class ObjCMethod;
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
#endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
|
||||
|
@@ -57,9 +57,8 @@
|
||||
#include "Control.h"
|
||||
#include "Literals.h"
|
||||
#include <cassert>
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
CheckDeclaration::CheckDeclaration(Semantic *semantic)
|
||||
: SemanticCheck(semantic),
|
||||
@@ -228,7 +227,6 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
|
||||
|
||||
if (it->declarator && it->declarator->initializer) {
|
||||
FullySpecifiedType initTy = semantic()->check(it->declarator->initializer, _scope);
|
||||
Q_UNUSED(initTy)
|
||||
}
|
||||
|
||||
*decl_it = new (translationUnit()->memoryPool()) List<Declaration *>();
|
||||
@@ -702,26 +700,26 @@ bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
|
||||
if (!attrAst)
|
||||
continue;
|
||||
|
||||
const char *attrName = spell(attrAst->attribute_identifier_token);
|
||||
if (!qstrcmp("getter", attrName)) {
|
||||
Identifier *attrId = identifier(attrAst->attribute_identifier_token);
|
||||
if (attrId == control()->objcGetterId()) {
|
||||
if (checkPropertyAttribute(attrAst, propAttrs, Getter)) {
|
||||
// TODO: find method declaration for getter
|
||||
}
|
||||
} else if (!qstrcmp("setter", attrName)) {
|
||||
} else if (attrId == control()->objcSetterId()) {
|
||||
if (checkPropertyAttribute(attrAst, propAttrs, Setter)) {
|
||||
// TODO: find method declaration for setter
|
||||
}
|
||||
} else if (!qstrcmp("readwrite", attrName)) {
|
||||
} else if (attrId == control()->objcReadwriteId()) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, ReadWrite);
|
||||
} else if (!qstrcmp("readonly", attrName)) {
|
||||
} else if (attrId == control()->objcReadonlyId()) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, ReadOnly);
|
||||
} else if (!qstrcmp("assign", attrName)) {
|
||||
} else if (attrId == control()->objcAssignId()) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, Assign);
|
||||
} else if (!qstrcmp("retain", attrName)) {
|
||||
} else if (attrId == control()->objcRetainId()) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, Retain);
|
||||
} else if (!qstrcmp("copy", attrName)) {
|
||||
} else if (attrId == control()->objcCopyId()) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, Copy);
|
||||
} else if (!qstrcmp("nonatomic", attrName)) {
|
||||
} else if (attrId == control()->objcNonatomicId()) {
|
||||
checkPropertyAttribute(attrAst, propAttrs, NonAtomic);
|
||||
}
|
||||
}
|
||||
@@ -745,4 +743,4 @@ bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "SemanticCheck.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT CheckDeclaration: public SemanticCheck
|
||||
{
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
bool _checkAnonymousArguments: 1;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CHECKDECLARATION_H
|
||||
|
@@ -55,7 +55,7 @@
|
||||
#include "CoreTypes.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
CheckDeclarator::CheckDeclarator(Semantic *semantic)
|
||||
: SemanticCheck(semantic),
|
||||
@@ -300,4 +300,4 @@ void CheckDeclarator::applyCvQualifiers(SpecifierAST *cv)
|
||||
}
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include "SemanticCheck.h"
|
||||
#include "FullySpecifiedType.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT CheckDeclarator: public SemanticCheck
|
||||
{
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
FullySpecifiedType _fullySpecifiedType;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CHECKDECLARATOR_H
|
||||
|
@@ -56,7 +56,7 @@
|
||||
#include "Symbols.h"
|
||||
#include "Control.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
CheckExpression::CheckExpression(Semantic *semantic)
|
||||
: SemanticCheck(semantic),
|
||||
@@ -207,7 +207,6 @@ bool CheckExpression::visit(NewExpressionAST *ast)
|
||||
if (ast->new_placement) {
|
||||
for (ExpressionListAST *it = ast->new_placement->expression_list; it; it = it->next) {
|
||||
FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
|
||||
Q_UNUSED(exprTy)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,18 +214,15 @@ bool CheckExpression::visit(NewExpressionAST *ast)
|
||||
|
||||
if (ast->new_type_id) {
|
||||
FullySpecifiedType ty = semantic()->check(ast->new_type_id->type_specifier, _scope);
|
||||
Q_UNUSED(ty)
|
||||
|
||||
for (NewArrayDeclaratorAST *it = ast->new_type_id->new_array_declarators; it; it = it->next) {
|
||||
FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
|
||||
Q_UNUSED(exprTy)
|
||||
}
|
||||
}
|
||||
|
||||
// ### process new-initializer
|
||||
if (ast->new_initializer) {
|
||||
FullySpecifiedType exprTy = semantic()->check(ast->new_initializer->expression, _scope);
|
||||
Q_UNUSED(exprTy)
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -397,4 +393,4 @@ bool CheckExpression::visit(ObjCSelectorExpressionAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include "SemanticCheck.h"
|
||||
#include "FullySpecifiedType.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT CheckExpression: public SemanticCheck
|
||||
{
|
||||
@@ -122,7 +122,7 @@ private:
|
||||
bool _checkOldStyleCasts: 1;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CHECKEXPRESSION_H
|
||||
|
@@ -58,7 +58,7 @@
|
||||
#include "Scope.h"
|
||||
#include <cassert>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
CheckName::CheckName(Semantic *semantic)
|
||||
: SemanticCheck(semantic),
|
||||
@@ -425,4 +425,4 @@ bool CheckName::visit(ObjCMessageArgumentDeclarationAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "SemanticCheck.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT CheckName: public SemanticCheck
|
||||
{
|
||||
@@ -89,7 +89,7 @@ private:
|
||||
Scope *_scope;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CHECKNAME_H
|
||||
|
@@ -58,7 +58,7 @@
|
||||
#include "Control.h"
|
||||
#include "Scope.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
CheckSpecifier::CheckSpecifier(Semantic *semantic)
|
||||
: SemanticCheck(semantic),
|
||||
@@ -420,4 +420,4 @@ bool CheckSpecifier::visit(ObjCTypeNameAST * /*ast*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include "SemanticCheck.h"
|
||||
#include "FullySpecifiedType.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT CheckSpecifier: public SemanticCheck
|
||||
{
|
||||
@@ -88,7 +88,7 @@ private:
|
||||
Scope *_scope;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CHECKSPECIFIER_H
|
||||
|
@@ -55,7 +55,7 @@
|
||||
#include "Control.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
CheckStatement::CheckStatement(Semantic *semantic)
|
||||
: SemanticCheck(semantic),
|
||||
@@ -307,4 +307,4 @@ bool CheckStatement::visit(WhileStatementAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "SemanticCheck.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT CheckStatement: public SemanticCheck
|
||||
{
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
Scope *_scope;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CHECKSTATEMENT_H
|
||||
|
@@ -57,7 +57,7 @@
|
||||
#include <map> // ### replace me with LiteralTable
|
||||
#include <string>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
|
||||
template <typename _Iterator>
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
: control(control),
|
||||
translationUnit(0),
|
||||
diagnosticClient(0)
|
||||
{ }
|
||||
{}
|
||||
|
||||
~Data()
|
||||
{
|
||||
@@ -577,10 +577,31 @@ public:
|
||||
std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
|
||||
std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations;
|
||||
std::vector<ObjCMethod *> objcMethods;
|
||||
|
||||
// ObjC context keywords:
|
||||
Identifier *objcGetterId;
|
||||
Identifier *objcSetterId;
|
||||
Identifier *objcReadwriteId;
|
||||
Identifier *objcReadonlyId;
|
||||
Identifier *objcAssignId;
|
||||
Identifier *objcRetainId;
|
||||
Identifier *objcCopyId;
|
||||
Identifier *objcNonatomicId;
|
||||
};
|
||||
|
||||
Control::Control()
|
||||
{ d = new Data(this); }
|
||||
{
|
||||
d = new Data(this);
|
||||
|
||||
d->objcGetterId = findOrInsertIdentifier("getter");
|
||||
d->objcSetterId = findOrInsertIdentifier("setter");
|
||||
d->objcReadwriteId = findOrInsertIdentifier("readwrite");
|
||||
d->objcReadonlyId = findOrInsertIdentifier("readonly");
|
||||
d->objcAssignId = findOrInsertIdentifier("assign");
|
||||
d->objcRetainId = findOrInsertIdentifier("retain");
|
||||
d->objcCopyId = findOrInsertIdentifier("copy");
|
||||
d->objcNonatomicId = findOrInsertIdentifier("nonatomic");
|
||||
}
|
||||
|
||||
Control::~Control()
|
||||
{ delete d; }
|
||||
@@ -766,4 +787,26 @@ ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsig
|
||||
ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, Name *name)
|
||||
{ return d->newObjCMethod(sourceLocation, name); }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
Identifier *Control::objcGetterId() const
|
||||
{ return d->objcGetterId; }
|
||||
|
||||
Identifier *Control::objcSetterId() const
|
||||
{ return d->objcSetterId; }
|
||||
|
||||
Identifier *Control::objcReadwriteId() const
|
||||
{ return d->objcReadwriteId; }
|
||||
|
||||
Identifier *Control::objcReadonlyId() const
|
||||
{ return d->objcReadonlyId; }
|
||||
|
||||
Identifier *Control::objcAssignId() const
|
||||
{ return d->objcAssignId; }
|
||||
|
||||
Identifier *Control::objcRetainId() const
|
||||
{ return d->objcRetainId; }
|
||||
|
||||
Identifier *Control::objcCopyId() const
|
||||
{ return d->objcCopyId; }
|
||||
|
||||
Identifier *Control::objcNonatomicId() const
|
||||
{ return d->objcNonatomicId; }
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include <cstddef>
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Control
|
||||
{
|
||||
@@ -169,6 +169,16 @@ public:
|
||||
/// Creates a new Objective-C method symbol.
|
||||
ObjCMethod *newObjCMethod(unsigned sourceLocation, Name *name = 0);
|
||||
|
||||
// Objective-C specific context keywords.
|
||||
Identifier *objcGetterId() const;
|
||||
Identifier *objcSetterId() const;
|
||||
Identifier *objcReadwriteId() const;
|
||||
Identifier *objcReadonlyId() const;
|
||||
Identifier *objcAssignId() const;
|
||||
Identifier *objcRetainId() const;
|
||||
Identifier *objcCopyId() const;
|
||||
Identifier *objcNonatomicId() const;
|
||||
|
||||
Identifier *findIdentifier(const char *chars, unsigned size) const;
|
||||
|
||||
Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
|
||||
@@ -199,7 +209,7 @@ private:
|
||||
Data *d;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CONTROL_H
|
||||
|
@@ -51,7 +51,7 @@
|
||||
#include "Names.h"
|
||||
#include <algorithm>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
|
||||
bool VoidType::isEqualTo(const Type *other) const
|
||||
@@ -230,4 +230,4 @@ bool NamedType::isEqualTo(const Type *other) const
|
||||
void NamedType::accept0(TypeVisitor *visitor)
|
||||
{ visitor->visit(this); }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -54,8 +54,8 @@
|
||||
#include "FullySpecifiedType.h"
|
||||
#include <cstddef>
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT UndefinedType : public Type
|
||||
{
|
||||
@@ -272,7 +272,7 @@ private:
|
||||
Name *_name;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_CORETYPES_H
|
||||
|
@@ -48,7 +48,7 @@
|
||||
|
||||
#include "DiagnosticClient.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
DiagnosticClient::DiagnosticClient()
|
||||
{ }
|
||||
@@ -56,4 +56,4 @@ DiagnosticClient::DiagnosticClient()
|
||||
DiagnosticClient::~DiagnosticClient()
|
||||
{ }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT DiagnosticClient
|
||||
{
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
const char *format, va_list ap) = 0;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_DIAGNOSTICCLIENT_H
|
||||
|
@@ -50,7 +50,7 @@
|
||||
#include "Type.h"
|
||||
#include "CoreTypes.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
FullySpecifiedType::FullySpecifiedType(Type *type) :
|
||||
_type(type), _flags(0)
|
||||
@@ -209,4 +209,4 @@ FullySpecifiedType FullySpecifiedType::simplified() const
|
||||
return *this;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -51,8 +51,8 @@
|
||||
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT FullySpecifiedType
|
||||
{
|
||||
@@ -151,7 +151,7 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_FULLYSPECIFIEDTYPE_H
|
||||
|
@@ -49,7 +49,7 @@
|
||||
#include "Lexer.h"
|
||||
#include "Token.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
static inline int classify2(const char *s, bool) {
|
||||
if (s[0] == 'd') {
|
||||
@@ -1400,4 +1400,4 @@ int Lexer::classifyOperator(const char *s, int n) {
|
||||
} // switch
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -55,7 +55,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
Lexer::Lexer(TranslationUnit *unit)
|
||||
: _translationUnit(unit),
|
||||
@@ -720,4 +720,4 @@ void Lexer::scan_helper(Token *tok)
|
||||
} // switch
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "Token.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Lexer
|
||||
{
|
||||
@@ -152,7 +152,7 @@ private:
|
||||
unsigned _currentLine;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_LEXER_H
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
template <typename _Literal>
|
||||
class LiteralTable
|
||||
@@ -185,7 +185,7 @@ protected:
|
||||
int _allocatedBuckets;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_LITERALTABLE_H
|
||||
|
@@ -53,7 +53,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Literal::Literal(const char *chars, unsigned size)
|
||||
@@ -227,4 +227,4 @@ bool Identifier::isEqualTo(const Identifier *other) const
|
||||
return ! strcmp(chars(), other->chars());
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "Token.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Literal
|
||||
{
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
bool isEqualTo(const Identifier *other) const;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_LITERALS_H
|
||||
|
@@ -51,7 +51,7 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -125,4 +125,4 @@ void Managed::operator delete(void *)
|
||||
void Managed::operator delete(void *, MemoryPool *)
|
||||
{ }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include <cstddef>
|
||||
#include <new>
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT MemoryPool
|
||||
{
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
void operator delete(void *, MemoryPool *);
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_MEMORYPOOL_H
|
||||
|
@@ -50,7 +50,7 @@
|
||||
#include "Names.h"
|
||||
#include "NameVisitor.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
Name::Name()
|
||||
{ }
|
||||
@@ -93,4 +93,4 @@ void Name::accept(Name *name, NameVisitor *visitor)
|
||||
name->accept(visitor);
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -51,8 +51,8 @@
|
||||
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Name
|
||||
{
|
||||
@@ -98,7 +98,7 @@ protected:
|
||||
virtual void accept0(NameVisitor *visitor) = 0;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_NAME_H
|
||||
|
@@ -49,7 +49,7 @@
|
||||
#include "NameVisitor.h"
|
||||
#include "Names.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
NameVisitor::NameVisitor()
|
||||
{ }
|
||||
@@ -60,4 +60,4 @@ NameVisitor::~NameVisitor()
|
||||
void NameVisitor::accept(Name *name)
|
||||
{ Name::accept(name, this); }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -51,8 +51,8 @@
|
||||
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT NameVisitor
|
||||
{
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
virtual void visit(SelectorNameId *) {}
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_NAMEVISITOR_H
|
||||
|
@@ -52,7 +52,7 @@
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
QualifiedNameId::QualifiedNameId(Name *const names[],
|
||||
unsigned nameCount,
|
||||
@@ -326,4 +326,4 @@ bool SelectorNameId::isEqualTo(const Name *other) const
|
||||
return true;
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -53,8 +53,8 @@
|
||||
#include "Name.h"
|
||||
#include "FullySpecifiedType.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT QualifiedNameId: public Name
|
||||
{
|
||||
@@ -304,7 +304,7 @@ private:
|
||||
bool _hasArguments;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_NAMES_H
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include "Lexer.h"
|
||||
#include "Token.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
static inline int classify3(const char *s) {
|
||||
if (s[0] == 'e') {
|
||||
@@ -461,4 +461,4 @@ int Lexer::classifyObjCAtKeyword(const char *s, int n) {
|
||||
} // switch
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "ObjectiveCTypeQualifiers.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
static inline int classify2(const char *s) {
|
||||
if (s[0] == 'N') {
|
||||
@@ -315,7 +315,7 @@ static inline int classify9(const char *s) {
|
||||
return Token_identifier;
|
||||
}
|
||||
|
||||
int classifyObjectiveCTypeQualifiers(const char *s, int n) {
|
||||
int CPlusPlus::classifyObjectiveCTypeQualifiers(const char *s, int n) {
|
||||
switch (n) {
|
||||
case 2: return classify2(s);
|
||||
case 3: return classify3(s);
|
||||
@@ -328,4 +328,4 @@ int classifyObjectiveCTypeQualifiers(const char *s, int n) {
|
||||
} // switch
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -31,8 +31,8 @@
|
||||
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
enum {
|
||||
Token_NO,
|
||||
@@ -65,7 +65,7 @@ enum {
|
||||
|
||||
CPLUSPLUS_EXPORT int classifyObjectiveCTypeQualifiers(const char *s, int n);
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_OBJC_TYPEQUALIFIERS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -54,8 +54,8 @@
|
||||
#include "Token.h"
|
||||
#include "TranslationUnit.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Parser
|
||||
{
|
||||
@@ -264,8 +264,9 @@ public:
|
||||
|
||||
void match(int kind, unsigned *token);
|
||||
|
||||
bool maybeFunctionCall(SimpleDeclarationAST *simpleDecl) const;
|
||||
bool maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const;
|
||||
bool maybeAmbiguousStatement(DeclarationStatementAST *ast) const;
|
||||
bool maybeForwardOrClassDeclaration(SpecifierAST *decl_specifier_seq) const;
|
||||
bool isPointerDeclaration(DeclarationStatementAST *ast) const;
|
||||
|
||||
private:
|
||||
bool switchTemplateArguments(bool templateArguments);
|
||||
@@ -302,7 +303,7 @@ private:
|
||||
void operator =(const Parser& source);
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_PARSER_H
|
||||
|
@@ -57,7 +57,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
Scope::Scope(ScopedSymbol *owner)
|
||||
: _owner(owner),
|
||||
@@ -312,4 +312,4 @@ Scope::iterator Scope::firstSymbol() const
|
||||
Scope::iterator Scope::lastSymbol() const
|
||||
{ return _symbols + _symbolCount + 1; }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -51,8 +51,8 @@
|
||||
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Scope
|
||||
{
|
||||
@@ -153,7 +153,7 @@ private:
|
||||
int _hashSize;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_SCOPE_H
|
||||
|
@@ -59,7 +59,7 @@
|
||||
#include "CheckExpression.h"
|
||||
#include "CheckName.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
class Semantic::Data
|
||||
{
|
||||
@@ -252,4 +252,4 @@ int Semantic::visibilityForClassKey(int tokenKind) const
|
||||
}
|
||||
}
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
@@ -52,8 +52,8 @@
|
||||
#include "CPlusPlusForwardDeclarations.h"
|
||||
#include "ASTfwd.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_HEADER
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT Semantic
|
||||
{
|
||||
@@ -114,7 +114,7 @@ private:
|
||||
Data *d;
|
||||
};
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
CPLUSPLUS_END_HEADER
|
||||
} // end of namespace CPlusPlus
|
||||
|
||||
|
||||
#endif // CPLUSPLUS_SEMANTIC_H
|
||||
|
@@ -49,7 +49,7 @@
|
||||
#include "SemanticCheck.h"
|
||||
#include "Semantic.h"
|
||||
|
||||
CPLUSPLUS_BEGIN_NAMESPACE
|
||||
using namespace CPlusPlus;
|
||||
|
||||
SemanticCheck::SemanticCheck(Semantic *semantic)
|
||||
: ASTVisitor(semantic->control()),
|
||||
@@ -65,4 +65,4 @@ Semantic *SemanticCheck::semantic() const
|
||||
Control *SemanticCheck::control() const
|
||||
{ return _semantic->control(); }
|
||||
|
||||
CPLUSPLUS_END_NAMESPACE
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user