Merge remote branch 'origin/1.3'

Conflicts:
	src/plugins/cpptools/cppcodecompletion.cpp
	src/plugins/debugger/gdb/remotegdbadapter.cpp
This commit is contained in:
Oswald Buddenhagen
2009-10-20 20:09:00 +02:00
121 changed files with 2856 additions and 1663 deletions

View File

@@ -2929,7 +2929,7 @@ static void qDumpQVector(QDumper &d)
d.putItemCount("value", n); d.putItemCount("value", n);
d.putItem("valueeditable", "false"); d.putItem("valueeditable", "false");
d.putItem("numchild", n); d.putItem("numchild", nn);
if (d.dumpChildren) { if (d.dumpChildren) {
QByteArray strippedInnerType = stripPointerType(d.innerType); QByteArray strippedInnerType = stripPointerType(d.innerType);
const char *stripped = innerIsPointerType ? strippedInnerType.data() : 0; const char *stripped = innerIsPointerType ? strippedInnerType.data() : 0;
@@ -2998,10 +2998,26 @@ static void qDumpQWeakPointer(QDumper &d)
#endif // QT_VERSION >= 0x040500 #endif // QT_VERSION >= 0x040500
#endif // QT_BOOTSTRAPPED #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) static void qDumpStdList(QDumper &d)
{ {
const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data); const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data);
#ifdef Q_CC_MSVC #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()); const int size = static_cast<int>(list.size());
if (size < 0) if (size < 0)
return; return;
@@ -3052,6 +3068,43 @@ static void qDumpStdList(QDumper &d)
d.disarm(); 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, /* Dump out an arbitrary map. To iterate the map,
* it is cast to a map of <KeyType,Value>. 'int' can be used for both * 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 * 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(); const int nn = map.size();
if (nn < 0) if (nn < 0)
return; 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(); Q_TYPENAME DummyType::const_iterator it = map.begin();
const Q_TYPENAME DummyType::const_iterator cend = map.end(); const Q_TYPENAME DummyType::const_iterator cend = map.end();
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it) 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(); const int nn = set.size();
if (nn < 0) if (nn < 0)
return; 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(); Q_TYPENAME DummyType::const_iterator it = set.begin();
const Q_TYPENAME DummyType::const_iterator cend = set.end(); const Q_TYPENAME DummyType::const_iterator cend = set.end();
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it) for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)

View File

@@ -48,13 +48,32 @@
// Test uninitialized variables allocing memory // Test uninitialized variables allocing memory
bool optTestUninitialized = false; 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> template <class T>
inline T* testAddress(T* in) inline T* testAddress(T* in)
{ {
return optTestUninitialized ? unsigned char *mem = 0;
(reinterpret_cast<T*>(new char[sizeof(T)])) if (optTestUninitialized) {
: in; 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. /* Test program for Dumper development/porting.
@@ -175,8 +194,10 @@ static int dumpQMapIntInt()
QMap<int,int> test; QMap<int,int> test;
QMapNode<int,int> mapNode; QMapNode<int,int> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode; const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(42, 43); if (!optEmptyContainers) {
test.insert(43, 44); test.insert(42, 43);
test.insert(43, 44);
}
prepareInBuffer("QMap", "local.qmapintint", "local.qmapintint", "int@int"); prepareInBuffer("QMap", "local.qmapintint", "local.qmapintint", "int@int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(int), sizeof(mapNode), valueOffset); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(int), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -189,8 +210,10 @@ static int dumpQMapIntString()
QMap<int,QString> test; QMap<int,QString> test;
QMapNode<int,QString> mapNode; QMapNode<int,QString> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode; const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(42, QLatin1String("fortytwo")); if (!optEmptyContainers) {
test.insert(43, QLatin1String("fortytree")); test.insert(42, QLatin1String("fortytwo"));
test.insert(43, QLatin1String("fortytree"));
}
prepareInBuffer("QMap", "local.qmapintqstring", "local.qmapintqstring", "int@QString"); prepareInBuffer("QMap", "local.qmapintqstring", "local.qmapintqstring", "int@QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(QString), sizeof(mapNode), valueOffset); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(QString), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -201,8 +224,10 @@ static int dumpQMapIntString()
static int dumpQSetInt() static int dumpQSetInt()
{ {
QSet<int> test; QSet<int> test;
test.insert(42); if (!optEmptyContainers) {
test.insert(43); test.insert(42);
test.insert(43);
}
prepareInBuffer("QSet", "local.qsetint", "local.qsetint", "int"); prepareInBuffer("QSet", "local.qsetint", "local.qsetint", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -216,9 +241,11 @@ static int dumpQMapQStringString()
QMap<QString,QString> test; QMap<QString,QString> test;
QMapNode<QString,QString> mapNode; QMapNode<QString,QString> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode; const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(QLatin1String("42s"), QLatin1String("fortytwo")); if (!optEmptyContainers) {
test.insert(QLatin1String("423"), QLatin1String("fortytree")); test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString"); 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); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(QString), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout); fputc('\n', stdout);
@@ -278,8 +305,10 @@ static int dumpStdWString()
static int dumpStdStringList() static int dumpStdStringList()
{ {
std::list<std::string> test; std::list<std::string> test;
test.push_back("item1"); if (!optEmptyContainers) {
test.push_back("item2"); test.push_back("item1");
test.push_back("item2");
}
prepareInBuffer("std::list", "local.stringlist", "local.stringlist", "std::string"); 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); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<std::string>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -290,8 +319,10 @@ static int dumpStdStringList()
static int dumpStdStringQList() static int dumpStdStringQList()
{ {
QList<std::string> test; QList<std::string> test;
test.push_back("item1"); if (!optEmptyContainers) {
test.push_back("item2"); test.push_back("item1");
test.push_back("item2");
}
prepareInBuffer("QList", "local.stringqlist", "local.stringqlist", "std::string"); prepareInBuffer("QList", "local.stringqlist", "local.stringqlist", "std::string");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), 0, 0, 0); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), 0, 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -302,8 +333,10 @@ static int dumpStdStringQList()
static int dumpStdIntList() static int dumpStdIntList()
{ {
std::list<int> test; std::list<int> test;
test.push_back(1); if (!optEmptyContainers) {
test.push_back(2); test.push_back(1);
test.push_back(2);
}
prepareInBuffer("std::list", "local.intlist", "local.intlist", "int"); prepareInBuffer("std::list", "local.intlist", "local.intlist", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -314,8 +347,10 @@ static int dumpStdIntList()
static int dumpStdIntVector() static int dumpStdIntVector()
{ {
std::vector<int> test; std::vector<int> test;
test.push_back(1); if (!optEmptyContainers) {
test.push_back(2); test.push_back(1);
test.push_back(2);
}
prepareInBuffer("std::vector", "local.intvector", "local.intvector", "int"); prepareInBuffer("std::vector", "local.intvector", "local.intvector", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -326,8 +361,10 @@ static int dumpStdIntVector()
static int dumpStdStringVector() static int dumpStdStringVector()
{ {
std::vector<std::string> test; std::vector<std::string> test;
test.push_back("item1"); if (!optEmptyContainers) {
test.push_back("item2"); test.push_back("item1");
test.push_back("item2");
}
prepareInBuffer("std::vector", "local.stringvector", "local.stringvector", "std::string"); 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); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -338,8 +375,10 @@ static int dumpStdStringVector()
static int dumpStdWStringVector() static int dumpStdWStringVector()
{ {
std::vector<std::wstring> test; std::vector<std::wstring> test;
test.push_back(L"item1"); if (!optEmptyContainers) {
test.push_back(L"item2"); test.push_back(L"item1");
test.push_back(L"item2");
}
prepareInBuffer("std::vector", "local.wstringvector", "local.wstringvector", "std::wstring"); 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); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::wstring), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -350,8 +389,10 @@ static int dumpStdWStringVector()
static int dumpStdIntSet() static int dumpStdIntSet()
{ {
std::set<int> test; std::set<int> test;
test.insert(1); if (!optEmptyContainers) {
test.insert(2); test.insert(1);
test.insert(2);
}
prepareInBuffer("std::set", "local.intset", "local.intset", "int"); prepareInBuffer("std::set", "local.intset", "local.intset", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -362,8 +403,10 @@ static int dumpStdIntSet()
static int dumpStdStringSet() static int dumpStdStringSet()
{ {
std::set<std::string> test; std::set<std::string> test;
test.insert("item1"); if (!optEmptyContainers) {
test.insert("item2"); test.insert("item1");
test.insert("item2");
}
prepareInBuffer("std::set", "local.stringset", "local.stringset", "std::string"); 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); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -374,8 +417,10 @@ static int dumpStdStringSet()
static int dumpStdQStringSet() static int dumpStdQStringSet()
{ {
std::set<QString> test; std::set<QString> test;
test.insert(QLatin1String("item1")); if (!optEmptyContainers) {
test.insert(QLatin1String("item2")); test.insert(QLatin1String("item1"));
test.insert(QLatin1String("item2"));
}
prepareInBuffer("std::set", "local.stringset", "local.stringset", "QString"); prepareInBuffer("std::set", "local.stringset", "local.stringset", "QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(std::list<int>::allocator_type), 0, 0); qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout); fputs(qDumpOutBuffer, stdout);
@@ -385,9 +430,11 @@ static int dumpStdQStringSet()
static int dumpStdMapIntString() 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")); 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; const int valueOffset = (char*)&(entry.second) - (char*)&entry;
prepareInBuffer("std::map", "local.stdmapintstring", "local.stdmapintstring", 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> > > >"); "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; typedef std::map<std::string,std::string> TestType;
TestType test; TestType test;
const TestType::value_type entry("K", "V"); const TestType::value_type entry("K", "V");
test.insert(entry); if (!optEmptyContainers) {
test.insert(entry);
}
const int valueOffset = (char*)&(entry.second) - (char*)&entry; const int valueOffset = (char*)&(entry.second) - (char*)&entry;
prepareInBuffer("std::map", "local.stdmapstringstring", "local.stdmapstringstring", 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> > > >"); "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; 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[]) int main(int argc, char *argv[])
{ {
printf("\nQt Creator Debugging Helper testing tool\n\n"); 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(); const TypeDumpFunctionMap::const_iterator cend = tdm.constEnd();
if (argc < 2) { if (argc < 2) {
printf("Usage: %s [-a]|<type1> <type2..>\n", argv[0]); usage(argv[0], tdm);
printf("Supported types: ");
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
fputs(qPrintable(it.key()), stdout);
fputc(' ', stdout);
}
fputc('\n', stdout);
return 0; 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; int rc = 0;
if (argc == 2 && !qstrcmp(argv[1], "-a")) { if (optTestAll) {
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) { for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
printf("\nTesting: %s\n", qPrintable(it.key())); const QString test = it.key();
rc += (*it.value())(); 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 { } else {
for (int i = 1; i < argc; i++) { foreach(const QString &test, tests) {
const char *arg = argv[i]; printf("\nTesting: %s\n", qPrintable(test));
printf("\nTesting: %s\n", arg); const TypeDumpFunctionMap::const_iterator it = tdm.constFind(test);
const TypeDumpFunctionMap::const_iterator it = tdm.constFind(QLatin1String(arg));
if (it == cend) { if (it == cend) {
rc = -1; rc = -1;
fprintf(stderr, "\nUnhandled type: %s\n", argv[i]); fprintf(stderr, "\nUnhandled type: %s\n", qPrintable(test));
} else { } else {
rc = (*it.value())(); rc = (*it.value())();
} }

View File

@@ -565,63 +565,63 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
const QChar ch3 = pos > 1 ? editor->characterAt(pos - 3) : QChar(); const QChar ch3 = pos > 1 ? editor->characterAt(pos - 3) : QChar();
int start = pos; int start = pos;
int k = T_EOF_SYMBOL; int completionKind = T_EOF_SYMBOL;
switch (ch.toLatin1()) { switch (ch.toLatin1()) {
case '.': case '.':
if (ch2 != QLatin1Char('.')) { if (ch2 != QLatin1Char('.')) {
k = T_DOT; completionKind = T_DOT;
--start; --start;
} }
break; break;
case ',': case ',':
k = T_COMMA; completionKind = T_COMMA;
--start; --start;
break; break;
case '(': case '(':
if (wantFunctionCall) { if (wantFunctionCall) {
k = T_LPAREN; completionKind = T_LPAREN;
--start; --start;
} }
break; break;
case ':': case ':':
if (ch3 != QLatin1Char(':') && ch2 == QLatin1Char(':')) { if (ch3 != QLatin1Char(':') && ch2 == QLatin1Char(':')) {
k = T_COLON_COLON; completionKind = T_COLON_COLON;
start -= 2; start -= 2;
} }
break; break;
case '>': case '>':
if (ch2 == QLatin1Char('-')) { if (ch2 == QLatin1Char('-')) {
k = T_ARROW; completionKind = T_ARROW;
start -= 2; start -= 2;
} }
break; break;
case '*': case '*':
if (ch2 == QLatin1Char('.')) { if (ch2 == QLatin1Char('.')) {
k = T_DOT_STAR; completionKind = T_DOT_STAR;
start -= 2; start -= 2;
} else if (ch3 == QLatin1Char('-') && ch2 == QLatin1Char('>')) { } else if (ch3 == QLatin1Char('-') && ch2 == QLatin1Char('>')) {
k = T_ARROW_STAR; completionKind = T_ARROW_STAR;
start -= 3; start -= 3;
} }
break; break;
case '\\': case '\\':
case '@': case '@':
if (ch2.isNull() || ch2.isSpace()) { if (ch2.isNull() || ch2.isSpace()) {
k = T_DOXY_COMMENT; completionKind = T_DOXY_COMMENT;
--start; --start;
} }
break; break;
case '<': case '<':
k = T_ANGLE_STRING_LITERAL; completionKind = T_ANGLE_STRING_LITERAL;
--start; --start;
break; break;
case '"': case '"':
k = T_STRING_LITERAL; completionKind = T_STRING_LITERAL;
--start; --start;
break; break;
case '/': case '/':
k = T_SLASH; completionKind = T_SLASH;
--start; --start;
break; break;
} }
@@ -634,20 +634,20 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
tc.setPosition(pos); tc.setPosition(pos);
// Include completion: make sure the quote character is the first one on the line // 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; QTextCursor s = tc;
s.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); s.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
QString sel = s.selectedText(); QString sel = s.selectedText();
if (sel.indexOf(QLatin1Char('"')) < sel.length() - 1) { if (sel.indexOf(QLatin1Char('"')) < sel.length() - 1) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
} }
if (k == T_COMMA) { if (completionKind == T_COMMA) {
ExpressionUnderCursor expressionUnderCursor; ExpressionUnderCursor expressionUnderCursor;
if (expressionUnderCursor.startOfFunctionCall(tc) == -1) { if (expressionUnderCursor.startOfFunctionCall(tc) == -1) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
} }
@@ -655,24 +655,24 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
static CPlusPlus::TokenUnderCursor tokenUnderCursor; static CPlusPlus::TokenUnderCursor tokenUnderCursor;
const SimpleToken tk = tokenUnderCursor(tc); const SimpleToken tk = tokenUnderCursor(tc);
if (k == T_DOXY_COMMENT && tk.isNot(T_DOXY_COMMENT)) { if (completionKind == T_DOXY_COMMENT && !(tk.is(T_DOXY_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
// Don't complete in comments or strings, but still check for include completion // Don't complete in comments or strings, but still check for include completion
else if (tk.is(T_COMMENT) || (tk.isLiteral() && else if (tk.is(T_COMMENT) || tk.is(T_CPP_COMMENT) ||
(k != T_STRING_LITERAL (tk.isLiteral() && (completionKind != T_STRING_LITERAL
&& k != T_ANGLE_STRING_LITERAL && completionKind != T_ANGLE_STRING_LITERAL
&& k != T_SLASH))) { && completionKind != T_SLASH))) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
// Include completion: can be triggered by slash, but only in a string // 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))) { else if (completionKind == T_SLASH && (tk.isNot(T_STRING_LITERAL) && tk.isNot(T_ANGLE_STRING_LITERAL))) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
else if (k == T_LPAREN) { else if (completionKind == T_LPAREN) {
const QList<SimpleToken> &tokens = tokenUnderCursor.tokens(); const QList<SimpleToken> &tokens = tokenUnderCursor.tokens();
int i = 0; int i = 0;
for (; i < tokens.size(); ++i) { for (; i < tokens.size(); ++i) {
@@ -688,12 +688,12 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
} }
if (i == tokens.size()) { if (i == tokens.size()) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
} }
// Check for include preprocessor directive // 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; bool include = false;
const QList<SimpleToken> &tokens = tokenUnderCursor.tokens(); const QList<SimpleToken> &tokens = tokenUnderCursor.tokens();
if (tokens.size() >= 3) { if (tokens.size() >= 3) {
@@ -709,13 +709,13 @@ static int startOfOperator(TextEditor::ITextEditable *editor,
} }
if (!include) { if (!include) {
k = T_EOF_SYMBOL; completionKind = T_EOF_SYMBOL;
start = pos; start = pos;
} }
} }
if (kind) if (kind)
*kind = k; *kind = completionKind;
return start; return start;
} }
@@ -1022,8 +1022,13 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
// find a scope that encloses the current location, starting from the lastVisibileSymbol // find a scope that encloses the current location, starting from the lastVisibileSymbol
// and moving outwards // and moving outwards
Scope *sc = context.symbol()->scope(); Scope *sc = 0;
while (sc->enclosingScope()) { if (context.symbol())
sc = context.symbol()->scope();
else if (context.thisDocument())
sc = context.thisDocument()->globalSymbols();
while (sc && sc->enclosingScope()) {
unsigned startLine, startColumn; unsigned startLine, startColumn;
context.thisDocument()->translationUnit()->getPosition(sc->owner()->startOffset(), &startLine, &startColumn); context.thisDocument()->translationUnit()->getPosition(sc->owner()->startOffset(), &startLine, &startColumn);
unsigned endLine, endColumn; unsigned endLine, endColumn;
@@ -1037,7 +1042,7 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
sc = sc->enclosingScope(); 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 // It may still be a function call. If the whole line parses as a function
// declaration, we should be certain that it isn't. // declaration, we should be certain that it isn't.
@@ -1066,10 +1071,18 @@ bool CppCodeCompletion::completeConstructorOrFunction(const QList<TypeOfExpressi
Overview overview; Overview overview;
overview.setShowArgumentNames(true); overview.setShowArgumentNames(true);
TextEditor::CompletionItem item(this); // get rid of parentheses and cv-qualifiers
item.text = overview(f->type()); QString completion = overview(f->type());
item.text = item.text.mid(1, item.text.size()-2); if (f->isVolatile() || f->isConst())
m_completions.append(item); 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; return true;
} }

View File

@@ -707,10 +707,17 @@ bool CdbDebugEngine::startAttachDebugger(qint64 pid, DebuggerStartMode sm, QStri
{ {
// Need to attrach invasively, otherwise, no notification signals // Need to attrach invasively, otherwise, no notification signals
// for for CreateProcess/ExitProcess occur. // for for CreateProcess/ExitProcess occur.
// As of version 6.11, the initial breakpoint suppression has no effect (see notifyException). // Initial breakpoint occur:
// when attaching to a console process starting up. However, there is no initial breakpoint // 1) Desired: When attaching to a crashed process
// (and no startup trap), when attaching to a running GUI process. // 2) Undesired: When starting up a console process, in conjunction
const ULONG flags = DEBUG_ATTACH_INVASIVE_RESUME_PROCESS|DEBUG_ATTACH_INVASIVE_NO_INITIAL_BREAK; // 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); const HRESULT hr = m_d->m_cif.debugClient->AttachProcess(NULL, pid, flags);
if (debugCDB) if (debugCDB)
qDebug() << "Attaching to " << pid << " using flags" << flags << " returns " << hr << executionStatusString(m_d->m_cif.debugControl); 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) void CdbDebugEngine::processTerminated(unsigned long exitCode)
{ {
manager()->showDebuggerOutput(LogMisc, tr("The process exited with exit code %1.").arg(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__); setState(InferiorShuttingDown, Q_FUNC_INFO, __LINE__);
m_d->setDebuggeeHandles(0, 0); m_d->setDebuggeeHandles(0, 0);
m_d->clearForRun(); m_d->clearForRun();
@@ -912,14 +922,11 @@ void CdbDebugEnginePrivate::endDebugging(EndDebuggingMode em)
errorMessage.clear(); errorMessage.clear();
} }
// Clean up resources (open files, etc.) // Clean up resources (open files, etc.)
m_engine->setState(AdapterShuttingDown, Q_FUNC_INFO, __LINE__); m_engine->setState(EngineShuttingDown, Q_FUNC_INFO, __LINE__);
clearForRun(); clearForRun();
const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE); const HRESULT hr = m_cif.debugClient->EndSession(DEBUG_END_PASSIVE);
if (SUCCEEDED(hr)) { m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__); if (!SUCCEEDED(hr)) {
} else {
m_engine->setState(AdapterShutdownFailed, Q_FUNC_INFO, __LINE__);
m_engine->setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr)); errorMessage = QString::fromLatin1("There were errors trying to end debugging: %1").arg(msgComFailed("EndSession", hr));
manager()->showDebuggerOutput(LogError, errorMessage); manager()->showDebuggerOutput(LogError, errorMessage);
} }

View File

@@ -341,6 +341,8 @@ void CdbDumperInitThread ::run()
CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager, CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager,
CdbComInterfaces *cif) : CdbComInterfaces *cif) :
m_tryInjectLoad(true), m_tryInjectLoad(true),
m_msgDisabled(QLatin1String("Dumpers are disabled")),
m_msgNotInScope(QLatin1String("Data not in scope")),
m_state(NotLoaded), m_state(NotLoaded),
m_manager(manager), m_manager(manager),
m_cif(cif), m_cif(cif),
@@ -561,8 +563,14 @@ CdbDumperHelper::CallResult
if (!writeToDebuggee(m_cif->debugDataSpaces, inBuffer, m_inBufferAddress, errorMessage)) if (!writeToDebuggee(m_cif->debugDataSpaces, inBuffer, m_inBufferAddress, errorMessage))
return CallFailed; 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; return CallSyntaxError;
}
// Set up call and a temporary breakpoint after it. // Set up call and a temporary breakpoint after it.
// Try to skip debuggee crash exceptions and dumper exceptions // Try to skip debuggee crash exceptions and dumper exceptions
// by using 'gN' (go not handled -> pass handling to dumper __try/__catch block) // 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(); errorMessage->clear();
// Check failure cache and supported types // Check failure cache and supported types
if (m_state == Disabled) { if (m_state == Disabled) {
*errorMessage = QLatin1String("Dumpers are disabled"); *errorMessage =m_msgDisabled;
return DumpNotHandled;
}
if (wd.error) {
*errorMessage =m_msgNotInScope;
return DumpNotHandled; return DumpNotHandled;
} }
if (m_failedTypes.contains(wd.type)) { if (m_failedTypes.contains(wd.type)) {

View File

@@ -134,6 +134,8 @@ private:
static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage); static bool writeToDebuggee(CIDebugDataSpaces *ds, const QByteArray &buffer, quint64 address, QString *errorMessage);
const bool m_tryInjectLoad; const bool m_tryInjectLoad;
const QString m_msgDisabled;
const QString m_msgNotInScope;
State m_state; State m_state;
DebuggerManager *m_manager; DebuggerManager *m_manager;
CdbComInterfaces *m_cif; CdbComInterfaces *m_cif;

View File

@@ -217,7 +217,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
bool handled = false; bool handled = false;
do { do {
if (!isPointerType(wd.type)) if (wd.error || !isPointerType(wd.type))
break; break;
const int classPos = wd.value.indexOf(" class "); const int classPos = wd.value.indexOf(" class ");
if (classPos == -1) if (classPos == -1)
@@ -396,9 +396,9 @@ bool CdbStackFrameContext::editorToolTip(const QString &iname,
*errorMessage = QString::fromLatin1("%1 not found.").arg(iname); *errorMessage = QString::fromLatin1("%1 not found.").arg(iname);
return false; return false;
} }
const WatchData wd = m_symbolContext->symbolAt(index);
// Check dumpers. Should actually be just one item. // 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; QList<WatchData> result;
if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, &result, errorMessage)) { if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, &result, errorMessage)) {
foreach (const WatchData &dwd, result) { foreach (const WatchData &dwd, result) {

View File

@@ -33,8 +33,11 @@
#include "cdbsymbolgroupcontext.h" #include "cdbsymbolgroupcontext.h"
#include "cdbdebugengine_p.h" #include "cdbdebugengine_p.h"
#include "cdbdumperhelper.h" #include "cdbdumperhelper.h"
#include "debuggeractions.h"
#include "debuggermanager.h"
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
namespace Debugger { namespace Debugger {
@@ -85,6 +88,7 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << frameCount; qDebug() << Q_FUNC_INFO << frameCount;
const QChar exclamationMark = QLatin1Char('!');
m_frameContexts.resize(frameCount); m_frameContexts.resize(frameCount);
qFill(m_frameContexts, static_cast<CdbStackFrameContext*>(0)); 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); frame.address = QString::fromLatin1("0x%1").arg(instructionOffset, 0, 16);
m_cif->debugSymbols->GetNameByOffsetWide(instructionOffset, wszBuf, MAX_PATH, 0, 0); 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)); 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; ULONG ulLine;
ULONG64 ul64Displacement; ULONG64 ul64Displacement;
@@ -160,7 +168,13 @@ CdbStackFrameContext *CdbStackTraceContext::frameContextAt(int index, QString *e
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage); *errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
return 0; 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) { if (!sc) {
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage); *errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
return 0; return 0;

View File

@@ -39,6 +39,9 @@
enum { debug = 0 }; enum { debug = 0 };
enum { debugInternalDumpers = 0 }; enum { debugInternalDumpers = 0 };
// name separator for shadowed variables
static const char iNameShadowDelimiter = '#';
static inline QString msgSymbolNotFound(const QString &s) static inline QString msgSymbolNotFound(const QString &s)
{ {
return QString::fromLatin1("The symbol '%1' could not be found.").arg(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; 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 // A helper function to extract a string value from a member function of
// IDebugSymbolGroup2 taking the symbol index and a character buffer. // IDebugSymbolGroup2 taking the symbol index and a character buffer.
// Pass in the the member function as '&IDebugSymbolGroup2::GetSymbolNameWide' // 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, CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix,
CIDebugSymbolGroup *symbolGroup) : CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables) :
m_prefix(prefix), m_prefix(prefix),
m_nameDelimiter(QLatin1Char('.')), m_nameDelimiter(QLatin1Char('.')),
m_uninitializedVariables(uninitializedVariables.toSet()),
m_symbolGroup(symbolGroup), m_symbolGroup(symbolGroup),
m_unnamedSymbolNumber(1) m_unnamedSymbolNumber(1)
{ {
} }
CdbSymbolGroupContext::~CdbSymbolGroupContext() CdbSymbolGroupContext::~CdbSymbolGroupContext()
@@ -144,9 +158,10 @@ CdbSymbolGroupContext::~CdbSymbolGroupContext()
CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix, CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix,
CIDebugSymbolGroup *symbolGroup, CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables,
QString *errorMessage) QString *errorMessage)
{ {
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup); CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup, uninitializedVariables);
if (!rc->init(errorMessage)) { if (!rc->init(errorMessage)) {
delete rc; delete rc;
return 0; 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); *errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO), msgComFailed("GetSymbolParameters", hr)).arg(count);
return false; return false;
} }
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, 0, count); populateINameIndexMap(m_prefix, DEBUG_ANY_ID, count);
} }
if (debug) if (debug)
qDebug() << Q_FUNC_INFO << '\n'<< toString(); qDebug() << Q_FUNC_INFO << '\n'<< toString(true);
return 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, 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; const QString symbolPrefix = prefix + m_nameDelimiter;
if (debug) if (debug)
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << start << count; qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << parentId << end;
const unsigned long end = m_symbolParameters.size(); for (unsigned long i = end - 1; ; i--) {
unsigned long seenChildren = 0;
// Skip over expanded children
for (unsigned long i = start; i < end && seenChildren < count; i++) {
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i); const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i);
if (parentId == p.ParentSymbol) { if (parentId == p.ParentSymbol) {
seenChildren++;
// "__formal" occurs when someone writes "void foo(int /* x */)..." // "__formal" occurs when someone writes "void foo(int /* x */)..."
static const QString unnamedFormalParameter = QLatin1String("__formal"); static const QString unnamedFormalParameter = QLatin1String("__formal");
QString symbolName = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i); 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 += QString::number(m_unnamedSymbolNumber++);
symbolName += QLatin1Char('>'); 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); m_inameIndexMap.insert(name, i);
if (getSymbolState(p) == ExpandedSymbol) 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 << " ";
str << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i); str << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
if (p.Flags & DEBUG_SYMBOL_IS_LOCAL) 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'; str << p << '\n';
} }
if (verbose) { if (verbose) {
@@ -348,7 +384,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
if (it.value() > index) if (it.value() > index)
it.value() += newSymbolCount; it.value() += newSymbolCount;
// insert the new symbols // insert the new symbols
populateINameIndexMap(prefix, index, index + 1, newSymbolCount); populateINameIndexMap(prefix, index, index + 1 + newSymbolCount);
if (debug > 1) if (debug > 1)
qDebug() << '<' << Q_FUNC_INFO << '\n' << prefix << index << '\n' << toString(); qDebug() << '<' << Q_FUNC_INFO << '\n' << prefix << index << '\n' << toString();
return true; return true;
@@ -365,14 +401,6 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
return m_inameIndexMap.key(index); 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" // check for "0x000", "0x000 class X"
static inline bool isNullPointer(const WatchData &wd) static inline bool isNullPointer(const WatchData &wd)
{ {
@@ -409,19 +437,35 @@ static inline QString fixValue(const QString &value)
return removeInnerTemplateType(value); return removeInnerTemplateType(value);
} }
WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
{ {
WatchData wd; WatchData wd;
wd.iname = symbolINameAt(index); wd.iname = symbolINameAt(index);
wd.exp = wd.iname; 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); 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. // For class hierarchies, we get sometimes complicated std::template types here.
// Remove them for display // (std::map extends std::tree<>... Remove them for display only.
wd.name = removeInnerTemplateType(lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1)); const QString fullShadowedName = WatchData::shadowedName(name, shadowedNumber);
wd.name = WatchData::shadowedName(removeInnerTemplateType(name), shadowedNumber);
wd.addr = hexSymbolOffset(m_symbolGroup, index); 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); const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
wd.setType(type);
wd.setValue(fixValue(value)); wd.setValue(fixValue(value));
wd.setChildrenNeeded(); // compensate side effects of above setters wd.setChildrenNeeded(); // compensate side effects of above setters
// Figure out children. The SubElement is only a guess unless the symbol, // 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 // If the symbol has children (expanded or not), we leave the 'Children' flag
// in 'needed' state. Suppress 0-pointers right ("0x000 class X") // in 'needed' state. Suppress 0-pointers right ("0x000 class X")
// here as they only lead to children with memory access errors. // 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); wd.setHasChildren(hasChildren);
if (debug > 1) if (debug > 1)
qDebug() << Q_FUNC_INFO << index << '\n' << wd.toString(); 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 CdbSymbolGroupContext::dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index)
{ {
WatchData rc = symbolAt(index); WatchData rc = watchDataAt(index);
dump(ds, &rc); dump(ds, &rc);
return rc; return rc;
} }

View File

@@ -69,12 +69,14 @@ class CdbSymbolGroupContext
{ {
Q_DISABLE_COPY(CdbSymbolGroupContext); Q_DISABLE_COPY(CdbSymbolGroupContext);
explicit CdbSymbolGroupContext(const QString &prefix, explicit CdbSymbolGroupContext(const QString &prefix,
CIDebugSymbolGroup *symbolGroup); CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables = QStringList());
public: public:
~CdbSymbolGroupContext(); ~CdbSymbolGroupContext();
static CdbSymbolGroupContext *create(const QString &prefix, static CdbSymbolGroupContext *create(const QString &prefix,
CIDebugSymbolGroup *symbolGroup, CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables,
QString *errorMessage); QString *errorMessage);
QString prefix() const { return m_prefix; } QString prefix() const { return m_prefix; }
@@ -118,7 +120,7 @@ public:
int dumpedOwner, int dumpedOwner,
OutputIterator it, QString *errorMessage); OutputIterator it, QString *errorMessage);
WatchData symbolAt(unsigned long index) const; WatchData watchDataAt(unsigned long index) const;
// Run the internal dumpers on the symbol // Run the internal dumpers on the symbol
WatchData dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index); WatchData dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index);
@@ -155,7 +157,7 @@ private:
unsigned long *parentId, unsigned long *parentId,
QString *errorMessage); QString *errorMessage);
bool expandSymbol(const QString &prefix, unsigned long index, 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; QString symbolINameAt(unsigned long index) const;
int dumpQString(CIDebugDataSpaces *ds, WatchData *wd); int dumpQString(CIDebugDataSpaces *ds, WatchData *wd);
@@ -166,6 +168,7 @@ private:
const QString m_prefix; const QString m_prefix;
const QChar m_nameDelimiter; const QChar m_nameDelimiter;
const QSet<QString> m_uninitializedVariables;
CIDebugSymbolGroup *m_symbolGroup; CIDebugSymbolGroup *m_symbolGroup;
NameIndexMap m_inameIndexMap; NameIndexMap m_inameIndexMap;

View File

@@ -61,7 +61,7 @@ bool CdbSymbolGroupContext::getDumpChildSymbols(CIDebugDataSpaces *ds, const QSt
for (int s = start; s < m_symbolParameters.size(); ++s) { for (int s = start; s < m_symbolParameters.size(); ++s) {
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s); const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s);
if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) { if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) {
WatchData wd = symbolAt(s); WatchData wd = watchDataAt(s);
// Run internal dumper, mark ownership // Run internal dumper, mark ownership
if (ds) { if (ds) {
switch (dump(ds, &wd)) { switch (dump(ds, &wd)) {

View File

@@ -229,6 +229,13 @@ DebuggerSettings *DebuggerSettings::instance()
item->setValue(false); item->setValue(false);
instance->insertItem(DebugDebuggingHelpers, item); 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 = new SavedAction(instance);
item->setText(tr("Recheck debugging helper availability")); item->setText(tr("Recheck debugging helper availability"));

View File

@@ -85,6 +85,8 @@ enum DebuggerActionCode
UseCustomDebuggingHelperLocation, UseCustomDebuggingHelperLocation,
CustomDebuggingHelperLocation, CustomDebuggingHelperLocation,
DebugDebuggingHelpers, DebugDebuggingHelpers,
UseCodeModel,
UseToolTipsInMainEditor, UseToolTipsInMainEditor,
UseToolTipsInLocalsView, UseToolTipsInLocalsView,

View File

@@ -79,15 +79,13 @@ enum DebuggerState
InferiorStopping, // Debuggee running, stop requested InferiorStopping, // Debuggee running, stop requested
InferiorStopped, // Debuggee stopped InferiorStopped, // Debuggee stopped
InferiorStopFailed, // Debuggee stopped InferiorStopFailed, // Debuggee not stopped, will kill debugger
InferiorShuttingDown, InferiorShuttingDown,
InferiorShutDown, InferiorShutDown,
InferiorShutdownFailed, InferiorShutdownFailed,
AdapterShuttingDown, EngineShuttingDown
//AdapterShutDown, // Use DebuggerNotReady instead
AdapterShutdownFailed,
}; };
enum DebuggerStartMode enum DebuggerStartMode

View File

@@ -61,6 +61,8 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/fancymainwindow.h> #include <utils/fancymainwindow.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
#include <cplusplus/CppDocument.h>
#include <cpptools/cppmodelmanagerinterface.h>
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QDir> #include <QtCore/QDir>
@@ -99,43 +101,35 @@
// gdbserver, the trk client etc are referred to as 'Adapter', // gdbserver, the trk client etc are referred to as 'Adapter',
// whereas the debugged process is referred to as 'Inferior'. // whereas the debugged process is referred to as 'Inferior'.
// //
// 0 == DebuggerNotReady // 0 == DebuggerNotReady
// | // |
// EngineStarting // EngineStarting
// | // |
// AdapterStarting --> AdapterStartFailed --> 0 // AdapterStarting --> AdapterStartFailed --> 0
// | // |
// AdapterStarted // AdapterStarted ------------------------------------.
// | // | v
// InferiorStarting --> InferiorStartFailed --> 0 // InferiorStarting ----> InferiorStartFailed -------->|
// | // | |
// (core) | (attach) (remote) // (core) | (attach) (term) (remote) |
// .-----------------<-|->--------------------. // .-----------------<-|->------------------. |
// | v | // | v | |
// InferiorUnrunnable | | // InferiorUnrunnable | (plain) | |
// | | v // | | (trk) | |
// | | (plain) // | | | |
// | | (trk) // | .--> InferiorRunningRequested | |
// | | // | | | | |
// | | .------------------------------------. // | | InferiorRunning | |
// | | v | // | | | | |
// | InferiorRunningRequested v | // | | InferiorStopping | |
// | | | | // | | | | |
// | .---- InferiorRunning | | // | '------ InferiorStopped <-----------' |
// | | | | | // | | v
// | | InferiorStopping | | // | InferiorShuttingDown -> InferiorShutdownFailed ---->|
// | | | | | // | | |
// | v v | | // | InferiorShutDown |
// | |<--- InferiorStopped <-----------' | // | | |
// | | | | // '--------> EngineShuttingDown <--------------------------------'
// | | `---------------------------------------'
// | |
// | '---> InferiorShuttingDown -> InferiorShutdownFailed
// | |
// | InferiorShutDown
// | |
// | v
// '------------> AdapterShuttingDown -> AdapterShutdownFailed --> 0
// | // |
// 0 // 0
// //
@@ -206,8 +200,7 @@ static const char *stateName(int s)
SN(InferiorShuttingDown) SN(InferiorShuttingDown)
SN(InferiorShutDown) SN(InferiorShutDown)
SN(InferiorShutdownFailed) SN(InferiorShutdownFailed)
SN(AdapterShuttingDown) SN(EngineShuttingDown)
SN(AdapterShutdownFailed)
} }
return "<unknown>"; return "<unknown>";
#undef SN #undef SN
@@ -290,6 +283,8 @@ struct DebuggerManagerPrivate
IDebuggerEngine *m_engine; IDebuggerEngine *m_engine;
DebuggerState m_state; DebuggerState m_state;
CPlusPlus::Snapshot m_codeModelSnapshot;
}; };
DebuggerManager *DebuggerManagerPrivate::instance = 0; DebuggerManager *DebuggerManagerPrivate::instance = 0;
@@ -610,6 +605,18 @@ WatchHandler *DebuggerManager::watchHandler() const
return d->m_watchHandler; 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 SourceFilesWindow *DebuggerManager::sourceFileWindow() const
{ {
return d->m_sourceFilesWindow; return d->m_sourceFilesWindow;
@@ -1013,6 +1020,7 @@ void DebuggerManager::exitDebugger()
// in turn will handle the cleanup. // in turn will handle the cleanup.
if (d->m_engine && state() != DebuggerNotReady) if (d->m_engine && state() != DebuggerNotReady)
d->m_engine->exitDebugger(); d->m_engine->exitDebugger();
d->m_codeModelSnapshot.clear();
} }
DebuggerStartParametersPtr DebuggerManager::startParameters() const DebuggerStartParametersPtr DebuggerManager::startParameters() const
@@ -1544,7 +1552,7 @@ static bool isAllowedTransition(int from, int to)
case AdapterStarting: case AdapterStarting:
return to == AdapterStarted || to == AdapterStartFailed; return to == AdapterStarted || to == AdapterStartFailed;
case AdapterStarted: case AdapterStarted:
return to == InferiorStarting; return to == InferiorStarting || to == EngineShuttingDown;
case AdapterStartFailed: case AdapterStartFailed:
return to == DebuggerNotReady; return to == DebuggerNotReady;
@@ -1552,37 +1560,38 @@ static bool isAllowedTransition(int from, int to)
return to == InferiorRunningRequested || to == InferiorStopped return to == InferiorRunningRequested || to == InferiorStopped
|| to == InferiorStartFailed || to == InferiorUnrunnable; || to == InferiorStartFailed || to == InferiorUnrunnable;
case InferiorStartFailed: case InferiorStartFailed:
return to == DebuggerNotReady; return to == EngineShuttingDown;
case InferiorRunningRequested: case InferiorRunningRequested:
return to == InferiorRunning; return to == InferiorRunning || to == InferiorStopped;
case InferiorRunning: case InferiorRunning:
return to == InferiorStopping || to == InferiorShuttingDown; return to == InferiorStopping;
case InferiorStopping: case InferiorStopping:
return to == InferiorStopped || to == InferiorStopFailed; return to == InferiorStopped || to == InferiorStopFailed;
case InferiorStopped: case InferiorStopped:
return to == InferiorRunningRequested || to == InferiorShuttingDown; return to == InferiorRunningRequested || to == InferiorShuttingDown;
case InferiorStopFailed: case InferiorStopFailed:
return to == DebuggerNotReady; return to == EngineShuttingDown;
case InferiorUnrunnable: case InferiorUnrunnable:
return to == AdapterShuttingDown; return to == EngineShuttingDown;
case InferiorShuttingDown: case InferiorShuttingDown:
return to == InferiorShutDown || to == InferiorShutdownFailed; return to == InferiorShutDown || to == InferiorShutdownFailed;
case InferiorShutDown: case InferiorShutDown:
return to == AdapterShuttingDown; return to == EngineShuttingDown;
case InferiorShutdownFailed:
return to == EngineShuttingDown;
case AdapterShuttingDown: case EngineShuttingDown:
return to == DebuggerNotReady; return to == DebuggerNotReady;
default:
qDebug() << "UNKNOWN STATE: " << from;
} }
qDebug() << "UNKNOWN STATE:" << from;
return false; return false;
} }
void DebuggerManager::setState(DebuggerState state) void DebuggerManager::setState(DebuggerState state, bool forced)
{ {
//STATE_DEBUG("STATUS CHANGE: FROM " << stateName(d->m_state) //STATE_DEBUG("STATUS CHANGE: FROM " << stateName(d->m_state)
// << " TO " << stateName(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); .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))) //if (!((d->m_state == -1 && state == 0) || (d->m_state == 0 && state == 0)))
// qDebug() << msg; // qDebug() << msg;
if (!isAllowedTransition(d->m_state, state)) if (!forced && !isAllowedTransition(d->m_state, state))
qDebug() << "UNEXPECTED STATE TRANSITION: " << msg; qDebug() << "UNEXPECTED STATE TRANSITION: " << msg;
showDebuggerOutput(LogDebug, msg); showDebuggerOutput(LogDebug, msg);
@@ -1685,8 +1694,7 @@ bool DebuggerManager::debuggerActionsEnabled() const
case InferiorShuttingDown: case InferiorShuttingDown:
case InferiorShutDown: case InferiorShutDown:
case InferiorShutdownFailed: case InferiorShutdownFailed:
case AdapterShuttingDown: case EngineShuttingDown:
case AdapterShutdownFailed:
break; break;
} }
return false; return false;
@@ -1763,9 +1771,9 @@ DebuggerState IDebuggerEngine::state() const
return m_manager->state(); 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);
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

View File

@@ -59,6 +59,10 @@ namespace TextEditor {
class ITextEditor; class ITextEditor;
} }
namespace CPlusPlus {
class Snapshot;
}
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -183,6 +187,8 @@ public:
QString *settingsCategory = 0, QString *settingsCategory = 0,
QString *settingsPage = 0) const; QString *settingsPage = 0) const;
const CPlusPlus::Snapshot &cppCodeModelSnapshot() const;
static DebuggerManager *instance(); static DebuggerManager *instance();
public slots: public slots:
@@ -235,6 +241,7 @@ public slots:
void setRegisterValue(int nr, const QString &value); void setRegisterValue(int nr, const QString &value);
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
void clearCppCodeModelSnapshot();
public slots: // FIXME public slots: // FIXME
void showDebuggerOutput(const QString &msg) void showDebuggerOutput(const QString &msg)
@@ -270,7 +277,8 @@ private:
Internal::ThreadsHandler *threadsHandler() const; Internal::ThreadsHandler *threadsHandler() const;
Internal::WatchHandler *watchHandler() const; Internal::WatchHandler *watchHandler() const;
Internal::SourceFilesWindow *sourceFileWindow() const; Internal::SourceFilesWindow *sourceFileWindow() const;
QWidget *threadsWindow() const; QWidget *threadsWindow() const;
Internal::DebuggerManagerActions debuggerManagerActions() const; Internal::DebuggerManagerActions debuggerManagerActions() const;
void notifyInferiorStopped(); void notifyInferiorStopped();
@@ -280,7 +288,7 @@ private:
void cleanupViews(); void cleanupViews();
void setState(DebuggerState state); void setState(DebuggerState state, bool forced = false);
// //
// internal implementation // internal implementation

View File

@@ -373,6 +373,9 @@ QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation), m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
m_ui.dumperLocationChooser); m_ui.dumperLocationChooser);
m_group.insert(theDebuggerAction(UseCodeModel),
m_ui.checkBoxUseCodeModel);
#ifdef QT_DEBUG #ifdef QT_DEBUG
m_group.insert(theDebuggerAction(DebugDebuggingHelpers), m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
m_ui.checkBoxDebugDebuggingHelpers); m_ui.checkBoxDebugDebuggingHelpers);

View File

@@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>403</width> <width>432</width>
<height>434</height> <height>434</height>
</rect> </rect>
</property> </property>
@@ -83,10 +83,20 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="Utils::PathChooser" name="dumperLocationChooser" native="true"/> <widget class="Utils::PathChooser" name="dumperLocationChooser"/>
</item> </item>
</layout> </layout>
</item> </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> <item>
<widget class="QCheckBox" name="checkBoxDebugDebuggingHelpers"> <widget class="QCheckBox" name="checkBoxDebugDebuggingHelpers">
<property name="toolTip"> <property name="toolTip">

View File

@@ -31,7 +31,6 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QObject>
#include <QtCore/QProcess> #include <QtCore/QProcess>
namespace Debugger { namespace Debugger {
@@ -47,35 +46,22 @@ AbstractGdbAdapter::~AbstractGdbAdapter()
disconnect(); disconnect();
} }
// This cannot be in the c'tor, as it would not connect the "virtual" slots void AbstractGdbAdapter::shutdown()
void AbstractGdbAdapter::commonInit()
{ {
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) void AbstractGdbAdapter::write(const QByteArray &data)
{ {
m_gdbProc.write(data); m_engine->m_gdbProc.write(data);
} }
bool AbstractGdbAdapter::isTrkAdapter() const bool AbstractGdbAdapter::isTrkAdapter() const

View File

@@ -42,7 +42,7 @@ namespace Internal {
// debugging and TrkGdbAdapter used for on-device debugging. // debugging and TrkGdbAdapter used for on-device debugging.
// In the PlainGdbAdapter case it's just a wrapper around a QProcess running // 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 // 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 class AbstractGdbAdapter : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -51,34 +51,44 @@ public:
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0); AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
virtual ~AbstractGdbAdapter(); virtual ~AbstractGdbAdapter();
QByteArray readAllStandardOutput();
QByteArray readAllStandardError();
virtual void write(const QByteArray &data); virtual void write(const QByteArray &data);
virtual bool isTrkAdapter() const; // isUtterlyBrokenAdapter virtual bool isTrkAdapter() const; // isUtterlyBrokenAdapter
virtual void startAdapter() = 0; virtual void startAdapter() = 0;
virtual void startInferior() = 0; virtual void startInferior() = 0;
virtual void startInferiorPhase2();
virtual void interruptInferior() = 0; virtual void interruptInferior() = 0;
virtual void shutdown() = 0; virtual void shutdown();
virtual const char *inferiorShutdownCommand() const;
virtual bool dumpersAvailable() const = 0; 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: signals:
void adapterStarted(); 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 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 adapterCrashed(const QString &msg);
void inferiorStartFailed(const QString &msg); // This triggers the initial breakpoint synchronization and causes
void inferiorShutDown(); // startInferiorPhase2() being called once done.
void inferiorShutdownFailed(const QString &msg); void inferiorPrepared();
void readyReadStandardOutput();
void readyReadStandardError();
// The adapter is still running just fine, but it failed to acquire a debuggee.
void inferiorStartFailed(const QString &msg);
protected: protected:
void commonInit();
DebuggerState state() const DebuggerState state() const
{ return m_engine->state(); } { return m_engine->state(); }
void setState(DebuggerState state) void setState(DebuggerState state)
@@ -89,17 +99,10 @@ protected:
{ m_engine->debugMessage(msg); } { m_engine->debugMessage(msg); }
void showStatusMessage(const QString &msg) const void showStatusMessage(const QString &msg) const
{ m_engine->showStatusMessage(msg); } { m_engine->showStatusMessage(msg); }
void showMessageBox(int icon, const QString &title, const QString &text) const
static QString msgGdbStopFailed(const QString &why); { m_engine->showMessageBox(icon, title, text); }
static QString msgInferiorStopFailed(const QString &why);
static QString msgAttachedToStoppedInferior();
static QString msgInferiorStarted();
static QString msgInferiorRunning();
static QString msgConnectRemoteServerFailed(const QString &why);
GdbEngine * const m_engine; GdbEngine * const m_engine;
QProcess m_gdbProc;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -29,7 +29,6 @@
#include "attachgdbadapter.h" #include "attachgdbadapter.h"
#include "debuggeractions.h"
#include "gdbengine.h" #include "gdbengine.h"
#include "procinterrupt.h" #include "procinterrupt.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
@@ -53,7 +52,6 @@ namespace Internal {
AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent) AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent) : AbstractGdbAdapter(engine, parent)
{ {
commonInit();
} }
void AttachGdbAdapter::startAdapter() void AttachGdbAdapter::startAdapter()
@@ -62,28 +60,12 @@ void AttachGdbAdapter::startAdapter()
setState(AdapterStarting); setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER")); debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs; if (!m_engine->startGdb())
gdbArgs.prepend(_("mi")); return;
gdbArgs.prepend(_("-i"));
QString location = theDebuggerStringSetting(GdbLocation);
m_gdbProc.start(location, gdbArgs);
}
void AttachGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit 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() void AttachGdbAdapter::startInferior()
{ {
QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
@@ -99,6 +81,7 @@ void AttachGdbAdapter::handleAttach(const GdbResponse &response)
QTC_ASSERT(state() == InferiorStopped, qDebug() << state()); QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
debugMessage(_("INFERIOR ATTACHED")); debugMessage(_("INFERIOR ATTACHED"));
showStatusMessage(msgAttachedToStoppedInferior()); showStatusMessage(msgAttachedToStoppedInferior());
emit inferiorPrepared();
m_engine->updateAll(); m_engine->updateAll();
} else { } else {
QString msg = __(response.data.findChild("msg").data()); QString msg = __(response.data.findChild("msg").data());
@@ -114,59 +97,5 @@ void AttachGdbAdapter::interruptInferior()
debugMessage(_("CANNOT INTERRUPT %1").arg(pid)); 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 Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -31,10 +31,6 @@
#define DEBUGGER_ATTACHGDBADAPTER_H #define DEBUGGER_ATTACHGDBADAPTER_H
#include "abstractgdbadapter.h" #include "abstractgdbadapter.h"
#include "gdbengine.h"
#include <QtCore/QDebug>
#include <QtCore/QProcess>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -57,16 +53,10 @@ public:
void startAdapter(); void startAdapter();
void startInferior(); void startInferior();
void interruptInferior(); void interruptInferior();
void shutdown(); const char *inferiorShutdownCommand() const { return "detach"; }
private: private:
void handleAttach(const GdbResponse &response); 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 } // namespace Internal

View File

@@ -35,7 +35,9 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtGui/QMessageBox>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -53,7 +55,6 @@ namespace Internal {
CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent) CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent) : AbstractGdbAdapter(engine, parent)
{ {
commonInit();
} }
void CoreGdbAdapter::startAdapter() void CoreGdbAdapter::startAdapter()
@@ -62,85 +63,42 @@ void CoreGdbAdapter::startAdapter()
setState(AdapterStarting); setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER")); debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs; if (!m_engine->startGdb())
gdbArgs.prepend(_("mi")); return;
gdbArgs.prepend(_("-i"));
QString location = theDebuggerStringSetting(GdbLocation);
m_gdbProc.start(location, gdbArgs);
}
void CoreGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit 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() void CoreGdbAdapter::startInferior()
{ {
QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QFileInfo fi(startParameters().coreFile);
m_executable = startParameters().executable; m_executable = startParameters().executable;
if (m_executable.isEmpty()) { if (m_executable.isEmpty()) {
#ifdef EXE_FROM_CORE
// Extra round trip to get executable name from core file. // Extra round trip to get executable name from core file.
// This is sometimes not the full name, so it can't be used // This is sometimes not the full name, so it can't be used
// as the generic solution. // as the generic solution.
// Quoting core name below fails in gdb 6.8-debian.
QString coreName = fi.absoluteFilePath(); m_round = 1;
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore1)); loadCoreFile();
} else { #else
// Directly load symbols. showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"),
QFileInfo fi(m_executable); tr("No executable to load symbols from specified."));
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"") #endif
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols)); 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()); // Do that first, otherwise no symbols are loaded.
if (response.resultClass == GdbResultDone) { QFileInfo fi(m_executable);
showStatusMessage(tr("Attached to core temporarily.")); m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
GdbMi console = response.data.findChild("consolestreamoutput"); .arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
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);
}
} }
void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response) void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
@@ -148,74 +106,70 @@ void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) { if (response.resultClass == GdbResultDone) {
showStatusMessage(tr("Symbols found.")); 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 { } else {
QString msg = tr("Symbols not found in \"%1\" failed:\n%2") QString msg = tr("Loading symbols from \"%1\" failed:\n").arg(m_executable)
.arg(__(response.data.findChild("msg").data())); + __(response.data.findChild("msg").data());
setState(InferiorUnrunnable); showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), msg);
m_engine->updateAll();
// emit inferiorStartFailed(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()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) { 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.")); showStatusMessage(tr("Attached to core."));
setState(InferiorUnrunnable); setState(InferiorUnrunnable);
m_engine->updateAll(); m_engine->updateAll();
} else { } else {
QString msg = tr("Attach to core \"%1\" failed:\n%2") QString msg = tr("Attach to core \"%1\" failed:\n").arg(startParameters().coreFile)
.arg(__(response.data.findChild("msg").data())); + __(response.data.findChild("msg").data());
setState(InferiorUnrunnable); emit inferiorStartFailed(msg);
m_engine->updateAll();
// emit inferiorStartFailed(msg);
} }
} }
void CoreGdbAdapter::interruptInferior() void CoreGdbAdapter::interruptInferior()
{ {
// A core should never 'run' // A core should never 'run'
QTC_ASSERT(false, /**/); 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 Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -31,10 +31,10 @@
#define DEBUGGER_COREGDBADAPTER_H #define DEBUGGER_COREGDBADAPTER_H
#include "abstractgdbadapter.h" #include "abstractgdbadapter.h"
#include "gdbengine.h"
#include <QtCore/QDebug> #ifdef Q_OS_LINUX
#include <QtCore/QProcess> # define EXE_FROM_CORE
#endif
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -57,19 +57,16 @@ public:
void startAdapter(); void startAdapter();
void startInferior(); void startInferior();
void interruptInferior(); void interruptInferior();
void shutdown();
private: private:
void handleTargetCore1(const GdbResponse &response); void loadExeAndSyms();
void handleDetach1(const GdbResponse &response); void loadCoreFile();
void handleFileExecAndSymbols(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response);
void handleTargetCore2(const GdbResponse &response); void handleTargetCore(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);
#ifdef EXE_FROM_CORE
int m_round;
#endif
QString m_executable; QString m_executable;
}; };

View File

@@ -16,6 +16,7 @@ HEADERS += \
$$PWD/attachgdbadapter.h \ $$PWD/attachgdbadapter.h \
$$PWD/coregdbadapter.h \ $$PWD/coregdbadapter.h \
$$PWD/plaingdbadapter.h \ $$PWD/plaingdbadapter.h \
$$PWD/termgdbadapter.h \
$$PWD/remotegdbadapter.h \ $$PWD/remotegdbadapter.h \
$$PWD/trkgdbadapter.h \ $$PWD/trkgdbadapter.h \
@@ -30,6 +31,7 @@ SOURCES += \
$$PWD/attachgdbadapter.cpp \ $$PWD/attachgdbadapter.cpp \
$$PWD/coregdbadapter.cpp \ $$PWD/coregdbadapter.cpp \
$$PWD/plaingdbadapter.cpp \ $$PWD/plaingdbadapter.cpp \
$$PWD/termgdbadapter.cpp \
$$PWD/remotegdbadapter.cpp \ $$PWD/remotegdbadapter.cpp \
$$PWD/trkgdbadapter.cpp \ $$PWD/trkgdbadapter.cpp \

View File

@@ -37,6 +37,7 @@
#include "attachgdbadapter.h" #include "attachgdbadapter.h"
#include "coregdbadapter.h" #include "coregdbadapter.h"
#include "plaingdbadapter.h" #include "plaingdbadapter.h"
#include "termgdbadapter.h"
#include "remotegdbadapter.h" #include "remotegdbadapter.h"
#include "trkgdbadapter.h" #include "trkgdbadapter.h"
@@ -89,10 +90,6 @@
#endif #endif
#include <ctype.h> #include <ctype.h>
// FIXME: temporary hack to evalaute tbreak based step-over behaviour
static QString lastFile;
static int lastLine;
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -109,17 +106,29 @@ namespace Internal {
static bool stateAcceptsGdbCommands(DebuggerState state) static bool stateAcceptsGdbCommands(DebuggerState state)
{ {
return state == AdapterStarted switch (state) {
|| state == InferiorUnrunnable case AdapterStarting:
|| state == InferiorStarting case AdapterStarted:
|| state == InferiorRunningRequested case AdapterStartFailed:
|| state == InferiorRunning case InferiorUnrunnable:
|| state == InferiorStopping case InferiorStarting:
|| state == InferiorStopped case InferiorStartFailed:
|| state == InferiorShuttingDown case InferiorRunningRequested:
|| state == InferiorShutDown case InferiorRunning:
|| state == AdapterShuttingDown; 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 &currentToken() static int &currentToken()
{ {
@@ -221,27 +230,16 @@ GdbEngine::~GdbEngine()
void GdbEngine::connectAdapter() 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()), connect(m_gdbAdapter, SIGNAL(adapterStarted()),
this, SLOT(handleAdapterStarted())); this, SLOT(handleAdapterStarted()));
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)), connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
this, SLOT(handleAdapterStartFailed(QString,QString))); this, SLOT(handleAdapterStartFailed(QString,QString)));
connect(m_gdbAdapter, SIGNAL(adapterShutDown()),
this, SLOT(handleAdapterShutDown())); connect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)), this, SLOT(handleInferiorPrepared()));
this, SLOT(handleAdapterShutdownFailed(QString)));
connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)), connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
this, SLOT(handleInferiorStartFailed(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)), connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)),
this, SLOT(handleAdapterCrashed(QString))); this, SLOT(handleAdapterCrashed(QString)));
@@ -265,7 +263,6 @@ void GdbEngine::initializeVariables()
m_commandsDoneCallback = 0; m_commandsDoneCallback = 0;
m_commandsToRunOnTemporaryBreak.clear(); m_commandsToRunOnTemporaryBreak.clear();
m_cookieForToken.clear(); m_cookieForToken.clear();
m_customOutputForToken.clear();
m_pendingConsoleStreamOutput.clear(); m_pendingConsoleStreamOutput.clear();
m_pendingLogStreamOutput.clear(); m_pendingLogStreamOutput.clear();
@@ -561,11 +558,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
m_pendingLogStreamOutput); m_pendingLogStreamOutput);
response.data.setStreamOutput("consolestreamoutput", response.data.setStreamOutput("consolestreamoutput",
m_pendingConsoleStreamOutput); m_pendingConsoleStreamOutput);
QByteArray custom = m_customOutputForToken[token];
if (!custom.isEmpty())
response.data.setStreamOutput("customvaluecontents",
'{' + custom + '}');
//m_customOutputForToken.remove(token);
m_pendingLogStreamOutput.clear(); m_pendingLogStreamOutput.clear();
m_pendingConsoleStreamOutput.clear(); m_pendingConsoleStreamOutput.clear();
@@ -581,7 +573,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
void GdbEngine::readGdbStandardError() void GdbEngine::readGdbStandardError()
{ {
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError(); qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
} }
void GdbEngine::readGdbStandardOutput() void GdbEngine::readGdbStandardOutput()
@@ -589,7 +581,7 @@ void GdbEngine::readGdbStandardOutput()
int newstart = 0; int newstart = 0;
int scan = m_inbuffer.size(); int scan = m_inbuffer.size();
m_inbuffer.append(m_gdbAdapter->readAllStandardOutput()); m_inbuffer.append(m_gdbProc.readAllStandardOutput());
while (newstart < m_inbuffer.size()) { while (newstart < m_inbuffer.size()) {
int start = newstart; int start = newstart;
@@ -704,13 +696,13 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
} }
if (cmd.flags & NeedsStop) { if (cmd.flags & NeedsStop) {
if (state() == InferiorStopped || state() == AdapterStarted) { if (state() == InferiorStopped
|| state() == InferiorStarting || state() == AdapterStarted) {
// Can be safely sent now. // Can be safely sent now.
flushCommand(cmd); flushCommand(cmd);
} else { } else {
// Queue the commands that we cannot send at once. // Queue the commands that we cannot send at once.
showStatusMessage(tr("Stopping temporarily."), 1000); showStatusMessage(tr("Stopping temporarily."), 1000);
qDebug() << _("QUEUING COMMAND ") + cmd.command;
debugMessage(_("QUEUING COMMAND ") + cmd.command); debugMessage(_("QUEUING COMMAND ") + cmd.command);
m_commandsToRunOnTemporaryBreak.append(cmd); m_commandsToRunOnTemporaryBreak.append(cmd);
interruptInferior(); 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 #if 0
void GdbEngine::handleExecJumpToLine(const GdbResponse &response) void GdbEngine::handleExecJumpToLine(const GdbResponse &response)
{ {
@@ -1078,7 +1062,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern); QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern);
debugMessage(_("PATTERN: ") + pat); debugMessage(_("PATTERN: ") + pat);
postCommand(_("sharedlibrary ") + pat); postCommand(_("sharedlibrary ") + pat);
continueInferior(); continueInferiorInternal();
showStatusMessage(tr("Loading %1...").arg(dataStr)); showStatusMessage(tr("Loading %1...").arg(dataStr));
return; return;
} }
@@ -1093,7 +1077,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"} // args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
//if (reason == "signal-received" //if (reason == "signal-received"
// && data.findChild("signal-name").data() == "SIGTRAP") { // && data.findChild("signal-name").data() == "SIGTRAP") {
// continueInferior(); // continueInferiorInternal();
// return; // return;
//} //}
@@ -1194,7 +1178,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
reloadSourceFiles(); reloadSourceFiles();
postCommand(_("-break-list"), CB(handleBreakList)); postCommand(_("-break-list"), CB(handleBreakList));
QVariant var = QVariant::fromValue<GdbMi>(data); QVariant var = QVariant::fromValue<GdbMi>(data);
postCommand(_("p 0"), CB(handleStop2), var); // dummy postCommand(_("p 2"), CB(handleStop2), var); // dummy
} else { } else {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
// For some reason, attaching to a stopped process causes *two* stops // 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"); GdbMi frameData = data.findChild("frame");
if (frameData.findChild("func").data() == "_start" if (frameData.findChild("func").data() == "_start"
&& frameData.findChild("from").data() == "/lib/ld-linux.so.2") { && frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
setState(InferiorRunningRequested); continueInferiorInternal();
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
return; return;
} }
} }
@@ -1247,9 +1230,9 @@ void GdbEngine::handleStop2(const GdbResponse &response)
void GdbEngine::handleStop2(const GdbMi &data) void GdbEngine::handleStop2(const GdbMi &data)
{ {
// Sometimes we get some interesting extra information. Grab it. // Sometimes we get some interesting extra information. Grab it.
GdbMi frame = data.findChild("frame"); const GdbMi gdbmiFrame = data.findChild("frame");
GdbMi shortName = frame.findChild("file"); GdbMi shortName = gdbmiFrame.findChild("file");
GdbMi fullName = frame.findChild("fullname"); GdbMi fullName = gdbmiFrame.findChild("fullname");
if (shortName.isValid() && fullName.isValid()) { if (shortName.isValid() && fullName.isValid()) {
QString file = QFile::decodeName(shortName.data()); QString file = QFile::decodeName(shortName.data());
QString full = QFile::decodeName(fullName.data()); QString full = QFile::decodeName(fullName.data());
@@ -1260,16 +1243,17 @@ void GdbEngine::handleStop2(const GdbMi &data)
} }
// Quick shot: Jump to stack frame #0. // Quick shot: Jump to stack frame #0.
if (frame.isValid()) { StackFrame frame;
const StackFrame f = parseStackFrame(frame, 0); if (gdbmiFrame.isValid()) {
gotoLocation(f, true); frame = parseStackFrame(gdbmiFrame, 0);
gotoLocation(frame, true);
} }
// //
// Stack // Stack
// //
manager()->stackHandler()->setCurrentIndex(0); manager()->stackHandler()->setCurrentIndex(0);
updateLocals(); // Quick shot updateLocals(qVariantFromValue(frame)); // Quick shot
reloadStack(false); reloadStack(false);
@@ -1342,17 +1326,16 @@ void GdbEngine::handleExecContinue(const GdbResponse &response)
QTC_ASSERT(state() == InferiorRunning, /**/); QTC_ASSERT(state() == InferiorRunning, /**/);
} else { } else {
QTC_ASSERT(state() == InferiorRunningRequested, /**/); QTC_ASSERT(state() == InferiorRunningRequested, /**/);
setState(InferiorStopped);
QByteArray msg = response.data.findChild("msg").data(); QByteArray msg = response.data.findChild("msg").data();
if (msg.startsWith("Cannot find bounds of current function")) { if (msg.startsWith("Cannot find bounds of current function")) {
setState(InferiorStopped);
showStatusMessage(tr("Stopped."), 5000); showStatusMessage(tr("Stopped."), 5000);
//showStatusMessage(tr("No debug information available. " //showStatusMessage(tr("No debug information available. "
// "Leaving function...")); // "Leaving function..."));
//stepOutExec(); //stepOutExec();
} else { } else {
showMessageBox(QMessageBox::Critical, tr("Error"), showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg)); tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
QTC_ASSERT(state() == InferiorRunning, /**/);
shutdown(); shutdown();
} }
} }
@@ -1397,8 +1380,73 @@ QString GdbEngine::fullName(const QStringList &candidates)
void GdbEngine::shutdown() void GdbEngine::shutdown()
{ {
debugMessage(_("INITIATE GDBENGINE SHUTDOWN")); debugMessage(_("INITIATE GDBENGINE SHUTDOWN"));
initializeVariables(); switch (state()) {
m_gdbAdapter->shutdown(); 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() void GdbEngine::detachDebugger()
@@ -1414,8 +1462,7 @@ void GdbEngine::detachDebugger()
void GdbEngine::exitDebugger() // called from the manager void GdbEngine::exitDebugger() // called from the manager
{ {
disconnectDebuggingHelperActions(); disconnectDebuggingHelperActions();
initializeVariables(); shutdown();
m_gdbAdapter->shutdown();
} }
int GdbEngine::currentFrame() const int GdbEngine::currentFrame() const
@@ -1463,6 +1510,8 @@ AbstractGdbAdapter *GdbEngine::createAdapter(const DebuggerStartParametersPtr &s
case AttachExternal: case AttachExternal:
return new AttachGdbAdapter(this); return new AttachGdbAdapter(this);
default: default:
if (sp->useTerminal)
return new TermGdbAdapter(this);
return new PlainGdbAdapter(this); return new PlainGdbAdapter(this);
} }
} }
@@ -1476,25 +1525,23 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
// initializeVariables()); // initializeVariables());
//QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0); //QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0);
initializeVariables();
m_startParameters = sp; m_startParameters = sp;
delete m_gdbAdapter; delete m_gdbAdapter;
m_gdbAdapter = createAdapter(sp); m_gdbAdapter = createAdapter(sp);
connectAdapter();
if (startModeAllowsDumpers()) if (startModeAllowsDumpers())
connectDebuggingHelperActions(); connectDebuggingHelperActions();
initializeVariables();
connectAdapter();
m_gdbAdapter->startAdapter(); m_gdbAdapter->startAdapter();
} }
void GdbEngine::continueInferiorInternal() void GdbEngine::continueInferiorInternal()
{ {
QTC_ASSERT(state() == InferiorStopped, qDebug() << state()); QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
m_manager->resetLocation();
setTokenBarrier();
setState(InferiorRunningRequested); setState(InferiorRunningRequested);
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue)); postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
} }
@@ -1507,6 +1554,8 @@ void GdbEngine::autoContinueInferior()
void GdbEngine::continueInferior() void GdbEngine::continueInferior()
{ {
m_manager->resetLocation();
setTokenBarrier();
continueInferiorInternal(); continueInferiorInternal();
showStatusMessage(tr("Running requested..."), 5000); showStatusMessage(tr("Running requested..."), 5000);
} }
@@ -1589,12 +1638,10 @@ void GdbEngine::runToFunctionExec(const QString &functionName)
QTC_ASSERT(state() == InferiorStopped, qDebug() << state()); QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
setTokenBarrier(); setTokenBarrier();
postCommand(_("-break-insert -t ") + functionName); postCommand(_("-break-insert -t ") + functionName);
setState(InferiorRunningRequested); continueInferiorInternal();
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000); //setState(InferiorRunningRequested);
// that should be "^running". We need to handle the resulting
// "Stopped"
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
//postCommand(_("-exec-continue"), handleExecRunToFunction); //postCommand(_("-exec-continue"), handleExecRunToFunction);
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
} }
void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber) void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
@@ -1903,11 +1950,7 @@ void GdbEngine::handleBreakInsert(const GdbResponse &response)
const BreakpointData *data = handler->at(index); const BreakpointData *data = handler->at(index);
// Note that it is perfectly correct that the file name is put // Note that it is perfectly correct that the file name is put
// in quotes but not escaped. GDB simply is like that. // in quotes but not escaped. GDB simply is like that.
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
QFileInfo fi(data->fileName);
QString where = _c('"') + fi.fileName() + _("\":")
+ data->lineNumber;
#elif defined(Q_OS_MAC)
QFileInfo fi(data->fileName); QFileInfo fi(data->fileName);
QString where = _c('"') + fi.fileName() + _("\":") QString where = _c('"') + fi.fileName() + _("\":")
+ data->lineNumber; + 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, static void setWatchDataValue(WatchData &data, const GdbMi &mi,
int encoding = 0) int encoding = 0)
{ {
@@ -2818,8 +2856,8 @@ void GdbEngine::updateSubItem(const WatchData &data0)
qDebug() << "FIXME: GdbEngine::updateSubItem:" qDebug() << "FIXME: GdbEngine::updateSubItem:"
<< data.toString() << "should not happen"; << data.toString() << "should not happen";
#else #else
data.setType(strNotInScope); data.setType(WatchData::msgNotInScope());
data.setValue(strNotInScope); data.setValue(WatchData::msgNotInScope());
data.setHasChildren(false); data.setHasChildren(false);
insertData(data); insertData(data);
return; return;
@@ -2964,7 +3002,7 @@ void GdbEngine::updateWatchData(const WatchData &data)
if (isSynchroneous()) { if (isSynchroneous()) {
// This should only be called for fresh expanded items, not for // This should only be called for fresh expanded items, not for
// items that had their children retrieved earlier. // items that had their children retrieved earlier.
qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n"; //qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
#if 0 #if 0
WatchData data1 = data; WatchData data1 = data;
data1.setAllUnneeded(); data1.setAllUnneeded();
@@ -3153,7 +3191,7 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
} else { } else {
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data())); data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
if (data.isWatcher()) { if (data.isWatcher()) {
data.value = strNotInScope; data.value = WatchData::msgNotInScope();
data.type = _(" "); data.type = _(" ");
data.setAllUnneeded(); data.setAllUnneeded();
data.setHasChildren(false); data.setHasChildren(false);
@@ -3206,7 +3244,7 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResponse &response)
&& msg.startsWith(__("The program being debugged stopped while")) && msg.startsWith(__("The program being debugged stopped while"))
&& msg.contains(__("qDumpObjectData440"))) { && msg.contains(__("qDumpObjectData440"))) {
// Fake full stop // Fake full stop
postCommand(_("p 0"), CB(handleStop2)); // dummy postCommand(_("p 3"), CB(handleStop2)); // dummy
return; return;
} }
#endif #endif
@@ -3227,7 +3265,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResponse &response)
GdbMi contents; GdbMi contents;
if (!parseConsoleStream(response, &contents)) { if (!parseConsoleStream(response, &contents)) {
data.setError(strNotInScope); data.setError(WatchData::msgNotInScope());
insertData(data); insertData(data);
return; return;
} }
@@ -3320,7 +3358,7 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
// << " STREAM:" << out; // << " STREAM:" << out;
if (list.isEmpty()) { if (list.isEmpty()) {
//: Value for variable //: Value for variable
data.setError(strNotInScope); data.setError(WatchData::msgNotInScope());
data.setAllUnneeded(); data.setAllUnneeded();
insertData(data); insertData(data);
} else if (data.type == __("QString") } else if (data.type == __("QString")
@@ -3365,19 +3403,19 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
} }
} else { } else {
//: Value for variable //: Value for variable
data.setError(strNotInScope); data.setError(WatchData::msgNotInScope());
data.setAllUnneeded(); data.setAllUnneeded();
insertData(data); insertData(data);
} }
} else { } else {
WatchData data = response.cookie.value<WatchData>(); WatchData data = response.cookie.value<WatchData>();
data.setError(strNotInScope); data.setError(WatchData::msgNotInScope());
data.setAllUnneeded(); data.setAllUnneeded();
insertData(data); insertData(data);
} }
} }
void GdbEngine::updateLocals() void GdbEngine::updateLocals(const QVariant &cookie)
{ {
m_pendingRequests = 0; m_pendingRequests = 0;
m_processedNames.clear(); m_processedNames.clear();
@@ -3398,8 +3436,8 @@ void GdbEngine::updateLocals()
postCommand(_("bb %1 %2") postCommand(_("bb %1 %2")
.arg(int(theDebuggerBoolSetting(UseDebuggingHelpers))) .arg(int(theDebuggerBoolSetting(UseDebuggingHelpers)))
.arg(expanded.join(_(","))), .arg(expanded.join(_(","))),
WatchUpdate, CB(handleStackFrame1)); CB(handleStackFrame1));
postCommand(_("p 0"), WatchUpdate, CB(handleStackFrame2)); postCommand(_("p 1"), CB(handleStackFrame2));
} else { } else {
QString level = QString::number(currentFrame()); QString level = QString::number(currentFrame());
// '2' is 'list with type and value' // '2' is 'list with type and value'
@@ -3407,7 +3445,7 @@ void GdbEngine::updateLocals()
postCommand(cmd, WatchUpdate, CB(handleStackListArguments)); postCommand(cmd, WatchUpdate, CB(handleStackListArguments));
// '2' is 'list with type and value' // '2' is 'list with type and value'
postCommand(_("-stack-list-locals 2"), WatchUpdate, 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; out = m_firstChunk + out;
int pos = out.indexOf("locals="); int pos = out.indexOf("locals=");
if (pos != 0) { if (pos != 0) {
qDebug() << "DICARDING JUNK AT BEGIN OF RESPONSE: " qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: "
<< out.left(pos); << out.left(pos);
out = out.mid(pos); out = out.mid(pos);
} }
@@ -3455,7 +3493,9 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response)
// qDebug() << "READ: " << list.at(i).toString(); // qDebug() << "READ: " << list.at(i).toString();
manager()->watchHandler()->insertBulkData(list); manager()->watchHandler()->insertBulkData(list);
manager()->watchHandler()->updateWatchers(); // FIXME:
//manager()->watchHandler()->updateWatchers();
rebuildModel();
} else { } else {
QTC_ASSERT(false, /**/); QTC_ASSERT(false, /**/);
} }
@@ -3503,91 +3543,105 @@ void GdbEngine::handleStackListLocals(const GdbResponse &response)
// There could be shadowed variables // There could be shadowed variables
QList<GdbMi> locals = response.data.findChild("locals").children(); QList<GdbMi> locals = response.data.findChild("locals").children();
locals += m_currentFunctionArgs; locals += m_currentFunctionArgs;
QMap<QByteArray, int> seen;
setLocals(locals); // 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(); 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; // Local variables of inlined code are reported as
QMap<QByteArray, int> seen; // 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
// numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..."}}
QList<WatchData> list; // We do not want these at all. Current hypotheses is that those
foreach (const GdbMi &item, locals) { // "spurious" locals have _two_ "exp" field. Try to filter them:
// Local variables of inlined code are reported as #ifdef Q_OS_MAC
// 26^done,locals={varobj={exp="this",value="",name="var4",exp="this", int numExps = 0;
// numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..." foreach (const GdbMi &child, item.children())
// We do not want these at all. Current hypotheses is that those numExps += int(child.name() == "exp");
// "spurious" locals have _two_ "exp" field. Try to filter them: if (numExps > 1)
#ifdef Q_OS_MAC return WatchData();
int numExps = 0; QByteArray name = item.findChild("exp").data();
foreach (const GdbMi &child, item.children()) #else
numExps += int(child.name() == "exp"); QByteArray name = item.findChild("name").data();
if (numExps > 1) #endif
continue; const QMap<QByteArray, int>::iterator it = seen->find(name);
QByteArray name = item.findChild("exp").data(); if (it != seen->end()) {
#else const int n = it.value();
QByteArray name = item.findChild("name").data(); ++(it.value());
#endif WatchData data;
int n = seen.value(name); QString nam = _(name);
if (n) { data.iname = _("local.") + nam + QString::number(n + 1);
seen[name] = n + 1; //: Variable %1 is the variable name, %2 is a simple count
WatchData data; data.name = WatchData::shadowedName(nam, n);
QString nam = _(name); if (uninitializedVariables.contains(data.name)) {
data.iname = _("local.") + nam + QString::number(n + 1); data.setError(WatchData::msgNotInScope());
//: Variable %1 is the variable name, %2 is a simple count return data;
data.name = tr("%1 <shadowed %2>").arg(nam).arg(n); }
//: 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")); 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); 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) void GdbEngine::insertData(const WatchData &data0)
@@ -4112,9 +4166,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResponse &response)
void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker) void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
{ {
lastFile = frame.file; // qDebug() << "GOTO " << frame << setMarker;
lastLine = frame.line;
//qDebug() << "GOTO " << frame.toString() << setMarker;
m_manager->gotoLocation(frame, setMarker); m_manager->gotoLocation(frame, setMarker);
} }
@@ -4122,18 +4174,37 @@ void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
// Starting up & shutting down // 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(_("STARTING GDB ") + gdb);
debugMessage(_("ADAPTER START FAILED"));
Core::ICore::instance()->showWarningWithOptions(tr("Adapter start failed"), msg, QString(),
QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
shutdown();
}
void GdbEngine::handleAdapterStarted() m_gdbProc.disconnect(); // From any previous runs
{
debugMessage(_("ADAPTER SUCCESSFULLY STARTED, INITIALIZING GDB")); 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(_("show version"), CB(handleShowVersion));
postCommand(_("help bb"), CB(handleIsSynchroneous)); 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 // Initial attempt to set breakpoints
showStatusMessage(tr("Setting breakpoints...")); showStatusMessage(tr("Setting breakpoints..."));
attemptBreakpointSynchronization(); attemptBreakpointSynchronization();
QTC_ASSERT(m_commandsDoneCallback == 0, /**/); if (m_cookieForToken.isEmpty()) {
m_commandsDoneCallback = &GdbEngine::startInferior; startInferiorPhase2();
} else {
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
m_commandsDoneCallback = &GdbEngine::startInferiorPhase2;
}
} }
void GdbEngine::startInferior() void GdbEngine::startInferiorPhase2()
{ {
QTC_ASSERT(state() == AdapterStarted, qDebug() << state()); debugMessage(_("BREAKPOINTS SET, CONTINUING INFERIOR STARTUP"));
showStatusMessage(tr("Starting inferior...")); m_gdbAdapter->startInferiorPhase2();
setState(InferiorStarting);
m_gdbAdapter->startInferior();
} }
void GdbEngine::handleInferiorStartFailed(const QString &msg) void GdbEngine::handleInferiorStartFailed(const QString &msg)
@@ -4241,46 +4374,22 @@ void GdbEngine::handleInferiorStartFailed(const QString &msg)
shutdown(); 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) void GdbEngine::handleAdapterCrashed(const QString &msg)
{ {
debugMessage(_("ADAPTER CRASHED")); 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() // 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.
debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN")); // Don't bother with state transitions - this can happen in any state and
setState(DebuggerNotReady); // 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) // No point in being friendly here ...
{ m_gdbProc.terminate();
debugMessage(_("ADAPTER SHUTDOWN FAILED"));
showMessageBox(QMessageBox::Critical, tr("Adapter shutdown failed"), msg); if (!msg.isEmpty())
setState(DebuggerNotReady); showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
} }
void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const 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::MemoryAgentCookie);
Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie); Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie);
Q_DECLARE_METATYPE(Debugger::Internal::GdbMi); Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);

View File

@@ -92,84 +92,79 @@ private:
friend class AttachGdbAdapter; friend class AttachGdbAdapter;
friend class CoreGdbAdapter; friend class CoreGdbAdapter;
friend class PlainGdbAdapter; friend class PlainGdbAdapter;
friend class TermGdbAdapter;
friend class RemoteGdbAdapter; friend class RemoteGdbAdapter;
friend class TrkGdbAdapter; friend class TrkGdbAdapter;
// private: ////////// General Interface //////////
// IDebuggerEngine implementation
//
void stepExec();
void stepOutExec();
void nextExec();
void stepIExec();
void nextIExec();
void shutdown(); virtual void addOptionPages(QList<Core::IOptionsPage*> *opts) const;
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
void startDebugger(const DebuggerStartParametersPtr &sp);
void exitDebugger();
void detachDebugger();
void continueInferiorInternal(); virtual bool checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage= 0) const;
void autoContinueInferior();
void continueInferior();
void interruptInferior();
void runToLineExec(const QString &fileName, int lineNumber); virtual bool isGdbEngine() const { return true; }
void runToFunctionExec(const QString &functionName);
void jumpToLineExec(const QString &fileName, int lineNumber);
void activateFrame(int index); virtual void startDebugger(const DebuggerStartParametersPtr &sp);
void selectThread(int index); 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); private: ////////// General State //////////
void executeDebuggerCommand(const QString & command);
void watchPoint(const QPoint &);
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(); void initializeVariables();
QString fullName(const QString &fileName); DebuggerStartMode startMode() const;
// get one usable name out of these, try full names first const DebuggerStartParameters &startParameters() const
QString fullName(const QStringList &candidates); { 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 { enum GdbCommandFlag {
NoFlags = 0, NoFlags = 0,
NeedsStop = 1, // The command needs a stopped inferior 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 ExitRequest = 32 // Callback expect GdbResultExit instead of GdbResultDone
}; };
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag) Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
private:
private:
typedef void (GdbEngine::*GdbCommandCallback) typedef void (GdbEngine::*GdbCommandCallback)
(const GdbResponse &response); (const GdbResponse &response);
typedef void (AbstractGdbAdapter::*AdapterCallback) typedef void (AbstractGdbAdapter::*AdapterCallback)
@@ -230,65 +224,7 @@ private:
void postCommandHelper(const GdbCommand &cmd); void postCommandHelper(const GdbCommand &cmd);
void setTokenBarrier(); 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, GdbCommand> m_cookieForToken;
QHash<int, QByteArray> m_customOutputForToken;
QByteArray m_pendingConsoleStreamOutput; QByteArray m_pendingConsoleStreamOutput;
QByteArray m_pendingLogStreamOutput; QByteArray m_pendingLogStreamOutput;
@@ -298,13 +234,68 @@ private:
// out of date and discarded. // out of date and discarded.
int m_oldestAcceptableToken; 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_gdbVersion; // 6.8.0 is 680
int m_gdbBuildVersion; // MAC only? int m_gdbBuildVersion; // MAC only?
bool m_isSynchroneous; // Can act synchroneously? bool m_isSynchroneous; // Can act synchroneously?
// awful hack to keep track of used files private: ////////// Inferior Management //////////
QMap<QString, QString> m_shortToFullName;
QMap<QString, QString> m_fullToShortName; 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 // Breakpoint specific stuff
@@ -323,9 +314,13 @@ private:
// //
// Modules specific stuff // Modules specific stuff
// //
virtual void loadSymbols(const QString &moduleName);
virtual void loadAllSymbols();
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
void reloadModules(); void reloadModules();
void handleModulesList(const GdbResponse &response); void handleModulesList(const GdbResponse &response);
bool m_modulesListOutdated;
// //
// Register specific stuff // Register specific stuff
@@ -335,54 +330,83 @@ private:
void handleRegisterListNames(const GdbResponse &response); void handleRegisterListNames(const GdbResponse &response);
void handleRegisterListValues(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 // Source file specific stuff
// //
void reloadSourceFiles(); 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 // Stack specific stuff
// //
void updateAll();
void handleStackListFrames(const GdbResponse &response); void handleStackListFrames(const GdbResponse &response);
void handleStackSelectThread(const GdbResponse &response); void handleStackSelectThread(const GdbResponse &response);
void handleStackListThreads(const GdbResponse &response); void handleStackListThreads(const GdbResponse &response);
void handleStackFrame1(const GdbResponse &response); void handleStackFrame1(const GdbResponse &response);
void handleStackFrame2(const GdbResponse &response); void handleStackFrame2(const GdbResponse &response);
QByteArray m_firstChunk;
Q_SLOT void reloadStack(bool forceGotoLocation); Q_SLOT void reloadStack(bool forceGotoLocation);
Q_SLOT void reloadFullStack(); Q_SLOT void reloadFullStack();
int currentFrame() const;
QList<GdbMi> m_currentFunctionArgs;
// QByteArray m_firstChunk;
// Tooltip specific stuff QString m_currentFrame;
//
void sendToolTipCommand(const QString &command, const QString &cookie);
// //
// Watch specific stuff // 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 // FIXME: BaseClass. called to improve situation for a watch item
void updateSubItem(const WatchData &data); void updateSubItem(const WatchData &data);
void handleChildren(const WatchData &parent, const GdbMi &child,
QList<WatchData> *insertions);
void updateWatchData(const WatchData &data); void updateWatchData(const WatchData &data);
Q_SLOT void updateWatchDataHelper(const WatchData &data); Q_SLOT void updateWatchDataHelper(const WatchData &data);
void rebuildModel(); void rebuildModel();
bool showToolTip();
void insertData(const WatchData &data); void insertData(const WatchData &data);
void sendWatchParameters(const QByteArray &params0); void sendWatchParameters(const QByteArray &params0);
void createGdbVariable(const WatchData &data); 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 runDebuggingHelper(const WatchData &data, bool dumpChildren);
void runDirectDebuggingHelper(const WatchData &data, bool dumpChildren); void runDirectDebuggingHelper(const WatchData &data, bool dumpChildren);
bool hasDebuggingHelperForType(const QString &type) const; bool hasDebuggingHelperForType(const QString &type) const;
void handleVarListChildren(const GdbResponse &response); void handleVarListChildren(const GdbResponse &response);
void handleVarListChildrenHelper(const GdbMi &child,
const WatchData &parent);
void handleVarCreate(const GdbResponse &response); void handleVarCreate(const GdbResponse &response);
void handleVarAssign(const GdbResponse &response); void handleVarAssign(const GdbResponse &response);
void handleEvaluateExpression(const GdbResponse &response); void handleEvaluateExpression(const GdbResponse &response);
@@ -393,53 +417,42 @@ private:
void handleDebuggingHelperValue3(const GdbResponse &response); void handleDebuggingHelperValue3(const GdbResponse &response);
void handleDebuggingHelperEditValue(const GdbResponse &response); void handleDebuggingHelperEditValue(const GdbResponse &response);
void handleDebuggingHelperSetup(const GdbResponse &response); void handleDebuggingHelperSetup(const GdbResponse &response);
void updateLocals(const QVariant &cookie = QVariant());
void handleStackListLocals(const GdbResponse &response); 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 handleStackListArguments(const GdbResponse &response);
void handleVarListChildrenHelper(const GdbMi &child,
const WatchData &parent);
void setWatchDataType(WatchData &data, const GdbMi &mi); void setWatchDataType(WatchData &data, const GdbMi &mi);
void setWatchDataDisplayedType(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; QSet<QString> m_processedNames;
QtDumperHelper m_dumperHelper;
DebuggingHelperState m_debuggingHelperState;
QList<GdbMi> m_currentFunctionArgs;
QString m_currentFrame;
QMap<QString, QString> m_varToType; QMap<QString, QString> m_varToType;
typedef void (GdbEngine::*CommandsDoneCallback)(); private: ////////// Dumper Management //////////
// function called after all previous responses have been received
CommandsDoneCallback m_commandsDoneCallback;
void startInferior();
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; private: ////////// Convenience Functions //////////
// make sure to re-initialize new members in initializeVariables();
QSharedPointer<TrkOptions> m_trkOptions;
AbstractGdbAdapter *m_gdbAdapter;
public:
QString errorMessage(QProcess::ProcessError error); QString errorMessage(QProcess::ProcessError error);
void showMessageBox(int icon, const QString &title, const QString &text); void showMessageBox(int icon, const QString &title, const QString &text);
void debugMessage(const QString &msg); void debugMessage(const QString &msg);
void addOptionPages(QList<Core::IOptionsPage*> *opts) const; QMainWindow *mainWindow() const;
const DebuggerStartParameters &startParameters() const
{ return *m_startParameters; }
}; };
} // namespace Internal } // namespace Internal

View File

@@ -29,18 +29,13 @@
#include "plaingdbadapter.h" #include "plaingdbadapter.h"
#include "debuggeractions.h"
#include "gdbengine.h" #include "gdbengine.h"
#include "procinterrupt.h" #include "procinterrupt.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/fancymainwindow.h>
#include <coreplugin/icore.h>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QVariant>
#include <QtGui/QMessageBox>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -58,8 +53,6 @@ namespace Internal {
PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent) PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent) : AbstractGdbAdapter(engine, parent)
{ {
commonInit();
// Output // Output
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)), connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
engine, SLOT(readDebugeeOutput(QByteArray))); engine, SLOT(readDebugeeOutput(QByteArray)));
@@ -72,37 +65,27 @@ void PlainGdbAdapter::startAdapter()
debugMessage(_("TRYING TO START ADAPTER")); debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs; QStringList gdbArgs;
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
if (!m_outputCollector.listen()) { if (!m_outputCollector.listen()) {
emit adapterStartFailed(tr("Cannot set up communication with child process: %1") emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
.arg(m_outputCollector.errorString()), QString()); .arg(m_outputCollector.errorString()), QString());
return; return;
} }
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName()); gdbArgs.append(_("--tty=") + m_outputCollector.serverName());
if (!startParameters().workingDir.isEmpty()) if (!startParameters().workingDir.isEmpty())
m_gdbProc.setWorkingDirectory(startParameters().workingDir); m_engine->m_gdbProc.setWorkingDirectory(startParameters().workingDir);
if (!startParameters().environment.isEmpty()) 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(); emit adapterStarted();
} }
void PlainGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
}
void PlainGdbAdapter::startInferior() void PlainGdbAdapter::startInferior()
{ {
QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
@@ -118,9 +101,7 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
{ {
QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) { if (response.resultClass == GdbResultDone) {
//m_breakHandler->clearBreakMarkers(); emit inferiorPrepared();
setState(InferiorRunningRequested);
m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
} else { } else {
QString msg = tr("Starting executable failed:\n") + QString msg = tr("Starting executable failed:\n") +
__(response.data.findChild("msg").data()); __(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) void PlainGdbAdapter::handleExecRun(const GdbResponse &response)
{ {
if (response.resultClass == GdbResultRunning) { if (response.resultClass == GdbResultRunning) {
@@ -160,74 +147,6 @@ void PlainGdbAdapter::shutdown()
{ {
debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state())); debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
m_outputCollector.shutdown(); 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 } // namespace Internal

View File

@@ -31,11 +31,8 @@
#define DEBUGGER_PLAINGDBADAPTER_H #define DEBUGGER_PLAINGDBADAPTER_H
#include "abstractgdbadapter.h" #include "abstractgdbadapter.h"
#include "gdbengine.h"
#include "outputcollector.h"
#include <QtCore/QDebug> #include <outputcollector.h>
#include <QtCore/QProcess>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -57,19 +54,15 @@ public:
void startAdapter(); void startAdapter();
void startInferior(); void startInferior();
void startInferiorPhase2();
void interruptInferior(); void interruptInferior();
void shutdown(); void shutdown();
const char *inferiorShutdownCommand() const { return "kill"; }
private: private:
void handleFileExecAndSymbols(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response);
void handleKill(const GdbResponse &response);
void handleExit(const GdbResponse &response);
void handleExecRun(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; OutputCollector m_outputCollector;
}; };

View File

@@ -28,8 +28,8 @@
**************************************************************************/ **************************************************************************/
#include "remotegdbadapter.h" #include "remotegdbadapter.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#include "debuggeractions.h"
#include "gdbengine.h" #include "gdbengine.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -54,8 +54,6 @@ namespace Internal {
RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent) RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent) : AbstractGdbAdapter(engine, parent)
{ {
commonInit();
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)), connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(uploadProcError(QProcess::ProcessError))); this, SLOT(uploadProcError(QProcess::ProcessError)));
connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()), connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()),
@@ -70,14 +68,6 @@ void RemoteGdbAdapter::startAdapter()
setState(AdapterStarting); setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER")); 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 // FIXME: make asynchroneous
// Start the remote server // Start the remote server
if (startParameters().serverStartScript.isEmpty()) { if (startParameters().serverStartScript.isEmpty()) {
@@ -88,33 +78,19 @@ void RemoteGdbAdapter::startAdapter()
m_uploadProc.waitForStarted(); m_uploadProc.waitForStarted();
} }
// Start the debugger if (!m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
m_gdbProc.start(location, gdbArgs); // FIXME: cleanup missing
} return;
void RemoteGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit 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) void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
{ {
QString msg; QString msg;
switch (error) { switch (error) {
case QProcess::FailedToStart: case QProcess::FailedToStart:
msg = tr("The upload process failed to start. Either the " msg = tr("The upload process failed to start. Shell missing?");
"invoked script '%1' is missing, or you may have insufficient "
"permissions to invoke the program.")
.arg(theDebuggerStringSetting(GdbLocation));
break; break;
case QProcess::Crashed: case QProcess::Crashed:
msg = tr("The upload process crashed some time after starting " msg = tr("The upload process crashed some time after starting "
@@ -140,7 +116,7 @@ void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
} }
m_engine->showStatusMessage(msg); m_engine->showStatusMessage(msg);
QMessageBox::critical(m_engine->mainWindow(), tr("Error"), msg); showMessageBox(QMessageBox::Critical, tr("Error"), msg);
} }
void RemoteGdbAdapter::readUploadStandardOutput() void RemoteGdbAdapter::readUploadStandardOutput()
@@ -211,7 +187,7 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
// gdb server will stop the remote application itself. // gdb server will stop the remote application itself.
debugMessage(_("INFERIOR STARTED")); debugMessage(_("INFERIOR STARTED"));
showStatusMessage(msgAttachedToStoppedInferior()); showStatusMessage(msgAttachedToStoppedInferior());
m_engine->continueInferior(); emit inferiorPrepared();
} else { } else {
// 16^error,msg="hd:5555: Connection timed out." // 16^error,msg="hd:5555: Connection timed out."
QString msg = msgConnectRemoteServerFailed(__(record.data.findChild("msg").data())); 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() void RemoteGdbAdapter::interruptInferior()
{ {
m_engine->postCommand(_("-exec-interrupt")); m_engine->postCommand(_("-exec-interrupt"));
@@ -226,56 +207,7 @@ void RemoteGdbAdapter::interruptInferior()
void RemoteGdbAdapter::shutdown() void RemoteGdbAdapter::shutdown()
{ {
switch (state()) { // FIXME: cleanup missing
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();
} }
} // namespace Internal } // namespace Internal

View File

@@ -31,10 +31,6 @@
#define DEBUGGER_REMOTEGDBADAPTER_H #define DEBUGGER_REMOTEGDBADAPTER_H
#include "abstractgdbadapter.h" #include "abstractgdbadapter.h"
#include "gdbengine.h"
#include <QtCore/QDebug>
#include <QtCore/QProcess>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -56,6 +52,7 @@ public:
void startAdapter(); void startAdapter();
void startInferior(); void startInferior();
void startInferiorPhase2();
void interruptInferior(); void interruptInferior();
void shutdown(); void shutdown();
@@ -67,12 +64,6 @@ private:
void handleSetTargetAsync(const GdbResponse &response); void handleSetTargetAsync(const GdbResponse &response);
void handleFileExecAndSymbols(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response);
void handleTargetRemote(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; QProcess m_uploadProc;
}; };

View 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

View 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

View File

@@ -30,22 +30,24 @@
#include "trkgdbadapter.h" #include "trkgdbadapter.h"
#include "trkoptions.h" #include "trkoptions.h"
#include "trkoptionspage.h" #include "trkoptionspage.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#ifndef STANDALONE_RUNNER #ifndef STANDALONE_RUNNER
#include "gdbengine.h" #include "gdbengine.h"
#endif #endif
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <sys/types.h>
# include <unistd.h>
#endif
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtCore/QDir> #include <QtCore/QDir>
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <sys/types.h>
# include <unistd.h>
#endif
#define CB(callback) \ #define CB(callback) \
static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \ static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \
STRINGIFY(callback) STRINGIFY(callback)
@@ -204,10 +206,6 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
#endif #endif
m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset); 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()), connect(&m_rfcommProc, SIGNAL(readyReadStandardError()),
this, SLOT(handleRfcommReadyReadStandardError())); this, SLOT(handleRfcommReadyReadStandardError()));
connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()), connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()),
@@ -380,17 +378,6 @@ QByteArray TrkGdbAdapter::trkInterruptMessage()
return ba; 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) void TrkGdbAdapter::emitDelayedInferiorStartFailed(const QString &msg)
{ {
m_adapterFailMessage = msg; m_adapterFailMessage = msg;
@@ -428,6 +415,7 @@ void TrkGdbAdapter::waitForTrkConnect()
} }
m_trkDevice.sendTrkInitialPing(); m_trkDevice.sendTrkInitialPing();
sendTrkMessage(0x02); // Disconnect, as trk might be still connected
sendTrkMessage(0x01); // Connect sendTrkMessage(0x01); // Connect
sendTrkMessage(0x05, TrkCB(handleSupportMask)); sendTrkMessage(0x05, TrkCB(handleSupportMask));
sendTrkMessage(0x06, TrkCB(handleCpuType)); sendTrkMessage(0x06, TrkCB(handleCpuType));
@@ -437,7 +425,7 @@ void TrkGdbAdapter::waitForTrkConnect()
// "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File // "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
//sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
maybeAdapterStarted(); emit adapterStarted();
} }
void TrkGdbAdapter::logMessage(const QString &msg) void TrkGdbAdapter::logMessage(const QString &msg)
@@ -1527,52 +1515,6 @@ void TrkGdbAdapter::interruptInferior()
sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting..."); 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() void TrkGdbAdapter::startAdapter()
{ {
// Retrieve parameters // Retrieve parameters
@@ -1634,13 +1576,12 @@ void TrkGdbAdapter::startAdapter()
connect(m_gdbServer, SIGNAL(newConnection()), connect(m_gdbServer, SIGNAL(newConnection()),
this, SLOT(handleGdbConnection())); this, SLOT(handleGdbConnection()));
logMessage("STARTING GDB");
logMessage(_("### Starting gdb %1").arg(m_options->gdb));
QStringList gdbArgs; QStringList gdbArgs;
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
gdbArgs.append(QLatin1String("-i")); if (!m_engine->startGdb(gdbArgs, m_options->gdb)) {
gdbArgs.append(QLatin1String("mi")); cleanup();
m_gdbProc.start(m_options->gdb, gdbArgs); return;
}
waitForTrkConnect(); waitForTrkConnect();
} }
@@ -1701,8 +1642,7 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
{ {
QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (record.resultClass == GdbResultDone) { if (record.resultClass == GdbResultDone) {
setState(InferiorRunningRequested); emit inferiorPrepared();
m_engine->postCommand(_("-exec-continue"), GdbEngine::RunRequest, CB(handleFirstContinue));
} else { } else {
QString msg = tr("Connecting to trk server adapter failed:\n") QString msg = tr("Connecting to trk server adapter failed:\n")
+ _(record.data.findChild("msg").data()); + _(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()); m_engine->continueInferiorInternal();
if (record.resultClass == GdbResultDone) {
debugMessage(_("INFERIOR STARTED"));
showStatusMessage(msgInferiorRunning());
} else {
emit inferiorStartFailed(msgConnectRemoteServerFailed(record.toString()));
}
} }
// //
@@ -1794,7 +1728,7 @@ void TrkGdbAdapter::write(const QByteArray &data)
trkReadMemoryMessage(m_session.dataseg, 12)); trkReadMemoryMessage(m_session.dataseg, 12));
return; return;
} }
m_gdbProc.write(data); m_engine->m_gdbProc.write(data);
} }
uint oldPC; uint oldPC;
@@ -1992,79 +1926,7 @@ void TrkGdbAdapter::cleanup()
void TrkGdbAdapter::shutdown() void TrkGdbAdapter::shutdown()
{ {
switch (state()) { cleanup();
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);
}
} }
} // namespace Internal } // namespace Internal

View File

@@ -30,10 +30,11 @@
#ifndef DEBUGGER_TRKGDBADAPTER_H #ifndef DEBUGGER_TRKGDBADAPTER_H
#define DEBUGGER_TRKGDBADAPTER_H #define DEBUGGER_TRKGDBADAPTER_H
#include "abstractgdbadapter.h"
#include "trkutils.h" #include "trkutils.h"
#include "trkdevice.h" #include "trkdevice.h"
#include "trkoptions.h" #include "trkoptions.h"
#include "abstractgdbadapter.h"
#include <QtCore/QHash> #include <QtCore/QHash>
#include <QtCore/QPointer> #include <QtCore/QPointer>
@@ -163,8 +164,6 @@ public:
// //
void start(const QString &program, const QStringList &args, void start(const QString &program, const QStringList &args,
QIODevice::OpenMode mode = QIODevice::ReadWrite); QIODevice::OpenMode mode = QIODevice::ReadWrite);
QByteArray readAllStandardError();
QByteArray readAllStandardOutput();
void write(const QByteArray &data); void write(const QByteArray &data);
bool isTrkAdapter() const { return true; } bool isTrkAdapter() const { return true; }
bool dumpersAvailable() const { return false; } bool dumpersAvailable() const { return false; }
@@ -172,19 +171,16 @@ public:
private: private:
void startAdapter(); void startAdapter();
void startInferior(); void startInferior();
void startInferiorPhase2();
void interruptInferior(); void interruptInferior();
void shutdown(); void shutdown();
void cleanup(); void cleanup();
void emitDelayedAdapterStartFailed(const QString &msg);
Q_SLOT void slotEmitDelayedAdapterStartFailed();
void emitDelayedInferiorStartFailed(const QString &msg); void emitDelayedInferiorStartFailed(const QString &msg);
Q_SLOT void slotEmitDelayedInferiorStartFailed(); Q_SLOT void slotEmitDelayedInferiorStartFailed();
Q_SLOT void waitForTrkConnect(); Q_SLOT void waitForTrkConnect();
void handleKill(const GdbResponse &response);
void handleExit(const GdbResponse &response);
void handleTargetRemote(const GdbResponse &response); void handleTargetRemote(const GdbResponse &response);
void handleFirstContinue(const GdbResponse &response);
// //
// TRK // TRK
@@ -285,13 +281,6 @@ private:
bool sendGdbServerPacket(const QByteArray &packet, bool doFlush); bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
void tryAnswerGdbMemoryRequest(bool buffered); 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 void logMessage(const QString &msg); // triggers output() if m_verbose
Q_SLOT void trkLogMessage(const QString &msg); Q_SLOT void trkLogMessage(const QString &msg);

View File

@@ -123,7 +123,7 @@ public:
protected: protected:
void showStatusMessage(const QString &msg, int timeout = -1); void showStatusMessage(const QString &msg, int timeout = -1);
DebuggerState state() const; DebuggerState state() const;
void setState(DebuggerState state); void setState(DebuggerState state, bool forced = false);
DebuggerManager *manager() const { return m_manager; } DebuggerManager *manager() const { return m_manager; }
DebuggerManager *m_manager; DebuggerManager *m_manager;

View File

@@ -33,12 +33,17 @@
#include <QtCore/QString> #include <QtCore/QString>
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
QT_BEGIN_NAMESPACE
class QDebug;
QT_END_NAMESPACE
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
struct StackFrame struct StackFrame
{ {
StackFrame(); StackFrame();
void clear();
bool isUsable() const; bool isUsable() const;
QString toToolTip() const; QString toToolTip() const;
QString toString() const; QString toString() const;
@@ -52,6 +57,8 @@ struct StackFrame
QString address; QString address;
}; };
QDebug operator<<(QDebug d, const StackFrame &);
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -37,12 +37,23 @@
#include <QtCore/QDebug> #include <QtCore/QDebug>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
using namespace Debugger::Internal; namespace Debugger {
namespace Internal {
StackFrame::StackFrame() StackFrame::StackFrame()
: level(0), line(0) : level(0), line(0)
{} {}
void StackFrame::clear()
{
line = level = 0;
function.clear();
file.clear();
from.clear();
to.clear();
address.clear();
}
bool StackFrame::isUsable() const bool StackFrame::isUsable() const
{ {
return !file.isEmpty() && QFileInfo(file).isReadable(); return !file.isEmpty() && QFileInfo(file).isReadable();
@@ -52,12 +63,12 @@ QString StackFrame::toString() const
{ {
QString res; QString res;
QTextStream str(&res); QTextStream str(&res);
str << StackHandler::tr("Address:") << " " << address << " " str << StackHandler::tr("Address:") << ' ' << address << ' '
<< StackHandler::tr("Function:") << " " << function << " " << StackHandler::tr("Function:") << ' ' << function << ' '
<< StackHandler::tr("File:") << " " << file << " " << StackHandler::tr("File:") << ' ' << file << ' '
<< StackHandler::tr("Line:") << " " << line << " " << StackHandler::tr("Line:") << ' ' << line << ' '
<< StackHandler::tr("From:") << " " << from << " " << StackHandler::tr("From:") << ' ' << from << ' '
<< StackHandler::tr("To:") << " " << to; << StackHandler::tr("To:") << ' ' << to;
return res; return res;
} }
@@ -76,6 +87,23 @@ QString StackFrame::toToolTip() const
return res; 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 // StackHandler
@@ -379,3 +407,5 @@ void ThreadsHandler::notifyRunning()
it->notifyRunning(); it->notifyRunning();
emit dataChanged(index(0, 1), index(m_threads.size()- 1, ColumnCount - 1)); emit dataChanged(index(0, 1), index(m_threads.size()- 1, ColumnCount - 1));
} }
} // namespace Internal
} // namespace Debugger

View File

@@ -30,18 +30,11 @@
#include "threadswindow.h" #include "threadswindow.h"
#include "debuggeractions.h" #include "debuggeractions.h"
#include "stackhandler.h"
#include <utils/qtcassert.h> #include <QtGui/QAction>
#include <QtGui/QContextMenuEvent>
#include <QAction> #include <QtGui/QHeaderView>
#include <QComboBox> #include <QtGui/QMenu>
#include <QDebug>
#include <QHeaderView>
#include <QMenu>
#include <QResizeEvent>
#include <QTreeView>
#include <QVBoxLayout>
using Debugger::Internal::ThreadsWindow; using Debugger::Internal::ThreadsWindow;
@@ -63,46 +56,38 @@ ThreadsWindow::ThreadsWindow(QWidget *parent)
this, SLOT(setAlternatingRowColorsHelper(bool))); 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) void ThreadsWindow::rowActivated(const QModelIndex &index)
{ {
//qDebug() << "ACTIVATED: " << index.row() << index.column();
emit threadSelected(index.row()); emit threadSelected(index.row());
} }
void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev) void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev)
{ {
QMenu menu; QMenu menu;
QAction *act1 = menu.addAction(tr("Adjust column widths to contents")); QAction *adjustColumnAction = menu.addAction(tr("Adjust column widths to contents"));
QAction *act2 = menu.addAction(tr("Always adjust column widths to contents")); QAction *alwaysAdjustColumnAction = menu.addAction(tr("Always adjust column widths to contents"));
act2->setCheckable(true); alwaysAdjustColumnAction->setCheckable(true);
act2->setChecked(m_alwaysResizeColumnsToContents); alwaysAdjustColumnAction->setChecked(m_alwaysResizeColumnsToContents);
menu.addSeparator(); menu.addSeparator();
menu.addAction(theDebuggerAction(SettingsDialog)); menu.addAction(theDebuggerAction(SettingsDialog));
QAction *act = menu.exec(ev->globalPos()); QAction *act = menu.exec(ev->globalPos());
if(!act)
return;
if (act == act1) if (act == adjustColumnAction) {
resizeColumnsToContents(); resizeColumnsToContents();
else if (act == act2) } else if (act == alwaysAdjustColumnAction) {
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents); setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
}
} }
void ThreadsWindow::resizeColumnsToContents() void ThreadsWindow::resizeColumnsToContents()
{ {
resizeColumnToContents(0); const int columnCount = model()->columnCount();
//resizeColumnToContents(1); for (int c = 0 ; c < columnCount; c++)
resizeColumnToContents(c);
} }
void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on) void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on)
@@ -111,6 +96,4 @@ void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on)
QHeaderView::ResizeMode mode = on QHeaderView::ResizeMode mode = on
? QHeaderView::ResizeToContents : QHeaderView::Interactive; ? QHeaderView::ResizeToContents : QHeaderView::Interactive;
header()->setResizeMode(0, mode); header()->setResizeMode(0, mode);
//header()->setResizeMode(1, mode);
} }

View File

@@ -54,7 +54,6 @@ private slots:
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); } void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
private: private:
void resizeEvent(QResizeEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev); void contextMenuEvent(QContextMenuEvent *ev);
bool m_alwaysResizeColumnsToContents; bool m_alwaysResizeColumnsToContents;

View File

@@ -105,6 +105,7 @@ WatchData::WatchData() :
generation(-1), generation(-1),
valueEnabled(true), valueEnabled(true),
valueEditable(true), valueEditable(true),
error(false),
source(0), source(0),
state(InitialState), state(InitialState),
changed(false) changed(false)
@@ -127,7 +128,8 @@ bool WatchData::isEqual(const WatchData &other) const
&& framekey == other.framekey && framekey == other.framekey
&& hasChildren == other.hasChildren && hasChildren == other.hasChildren
&& valueEnabled == other.valueEnabled && valueEnabled == other.valueEnabled
&& valueEditable == other.valueEditable; && valueEditable == other.valueEditable
&& error == other.error;
} }
void WatchData::setError(const QString &msg) void WatchData::setError(const QString &msg)
@@ -137,6 +139,7 @@ void WatchData::setError(const QString &msg)
setHasChildren(false); setHasChildren(false);
valueEnabled = false; valueEnabled = false;
valueEditable = false; valueEditable = false;
error = true;
} }
void WatchData::setValue(const QString &value0) void WatchData::setValue(const QString &value0)
@@ -232,6 +235,8 @@ QString WatchData::toString() const
str << "iname=\"" << iname << doubleQuoteComma; str << "iname=\"" << iname << doubleQuoteComma;
if (!name.isEmpty() && name != iname) if (!name.isEmpty() && name != iname)
str << "name=\"" << name << doubleQuoteComma; str << "name=\"" << name << doubleQuoteComma;
if (error)
str << "error,";
if (!addr.isEmpty()) if (!addr.isEmpty())
str << "addr=\"" << addr << doubleQuoteComma; str << "addr=\"" << addr << doubleQuoteComma;
if (!exp.isEmpty()) if (!exp.isEmpty())
@@ -310,6 +315,19 @@ QString WatchData::toToolTip() const
return res; 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 // WatchModel
@@ -590,9 +608,10 @@ void WatchModel::fetchMore(const QModelIndex &index)
QTC_ASSERT(index.isValid(), return); QTC_ASSERT(index.isValid(), return);
QTC_ASSERT(!watchItem(index)->fetchTriggered, return); QTC_ASSERT(!watchItem(index)->fetchTriggered, return);
if (WatchItem *item = watchItem(index)) { if (WatchItem *item = watchItem(index)) {
m_handler->m_expandedINames.insert(item->iname);
item->fetchTriggered = true; item->fetchTriggered = true;
WatchData data = *item;
if (item->children.isEmpty()) { if (item->children.isEmpty()) {
WatchData data = *item;
data.setChildrenNeeded(); data.setChildrenNeeded();
m_handler->m_manager->updateWatchData(data); 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); WatchItem &data = *watchItem(index);
if (role == ExpandedRole) { 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); m_handler->m_expandedINames.insert(data.iname);
else } else {
m_handler->m_expandedINames.remove(data.iname); m_handler->m_expandedINames.remove(data.iname);
}
} else if (role == TypeFormatRole) { } else if (role == TypeFormatRole) {
m_handler->setFormat(data.type, value.toInt()); m_handler->setFormat(data.type, value.toInt());
} else if (role == IndividualFormatRole) { } else if (role == IndividualFormatRole) {

View File

@@ -117,6 +117,9 @@ public:
bool isEqual(const WatchData &other) const; bool isEqual(const WatchData &other) const;
static QString msgNotInScope();
static QString shadowedName(const QString &name, int seen);
public: public:
QString iname; // internal name sth like 'local.baz.public.a' QString iname; // internal name sth like 'local.baz.public.a'
QString exp; // the expression QString exp; // the expression
@@ -135,6 +138,7 @@ public:
int generation; // when updated? int generation; // when updated?
bool valueEnabled; // value will be greyed out or not bool valueEnabled; // value will be greyed out or not
bool valueEditable; // value will be editable bool valueEditable; // value will be editable
bool error;
private: private:

View File

@@ -43,6 +43,9 @@
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
#include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/Overview.h>
#include <Symbols.h>
#include <Scope.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
@@ -51,6 +54,7 @@
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
#include <QtCore/QHash>
#include <QtGui/QTextCursor> #include <QtGui/QTextCursor>
#include <QtGui/QPlainTextEdit> #include <QtGui/QPlainTextEdit>
@@ -59,6 +63,78 @@
#include <ctype.h> #include <ctype.h>
enum { debug = 0 }; 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 Debugger {
namespace Internal { namespace Internal {
@@ -217,6 +293,135 @@ QString stripPointerType(QString type)
return 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) QString gdbQuoteTypes(const QString &type)
{ {
// gdb does not understand sizeof(Core::IFile*). // gdb does not understand sizeof(Core::IFile*).

View File

@@ -45,6 +45,10 @@ namespace Core {
class IEditor; class IEditor;
} }
namespace CPlusPlus {
class Snapshot;
}
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -89,6 +93,15 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
// Decode string data as returned by the dumper helpers. // Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding); 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 /* Attempt to put common code of the dumper handling into a helper
* class. * class.
* "Custom dumper" is a library compiled against the current * "Custom dumper" is a library compiled against the current

View File

@@ -136,10 +136,10 @@ WatchWindow::WatchWindow(Type type, DebuggerManager *manager, QWidget *parent)
connect(act, SIGNAL(toggled(bool)), connect(act, SIGNAL(toggled(bool)),
this, SLOT(setAlternatingRowColorsHelper(bool))); this, SLOT(setAlternatingRowColorsHelper(bool)));
connect(this, SIGNAL(expanded(QModelIndex)), connect(this, SIGNAL(expanded(QModelIndex)),
this, SLOT(expandNode(QModelIndex))); this, SLOT(expandNode(QModelIndex)));
connect(this, SIGNAL(collapsed(QModelIndex)), connect(this, SIGNAL(collapsed(QModelIndex)),
this, SLOT(collapseNode(QModelIndex))); this, SLOT(collapseNode(QModelIndex)));
} }
void WatchWindow::expandNode(const QModelIndex &idx) 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 *actInsertNewWatchItem = menu.addAction(tr("Insert new watch item"));
QAction *actSelectWidgetToWatch = menu.addAction(tr("Select widget to watch")); QAction *actSelectWidgetToWatch = menu.addAction(tr("Select widget to watch"));
const bool actionsEnabled = m_manager->debuggerActionsEnabled();
const QString address = model()->data(mi0, AddressRole).toString(); const QString address = model()->data(mi0, AddressRole).toString();
QAction *actWatchKnownMemory = 0; QAction *actWatchKnownMemory = 0;
QAction *actWatchUnknownMemory = new QAction(tr("Open memory editor..."), &menu); QAction *actWatchUnknownMemory = new QAction(tr("Open memory editor..."), &menu);
actWatchUnknownMemory->setEnabled(m_manager->debuggerActionsEnabled()); actWatchUnknownMemory->setEnabled(actionsEnabled);
if (!address.isEmpty()) if (!address.isEmpty())
actWatchKnownMemory = new QAction(tr("Open memory editor at %1").arg(address), &menu); 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(RecheckDebuggingHelpers));
menu.addAction(theDebuggerAction(UseDebuggingHelpers)); 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.addSeparator();
menu.addAction(theDebuggerAction(UseToolTipsInLocalsView)); menu.addAction(theDebuggerAction(UseToolTipsInLocalsView));
@@ -311,6 +314,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
} else if (act == actSelectWidgetToWatch) { } else if (act == actSelectWidgetToWatch) {
grabMouse(Qt::CrossCursor); grabMouse(Qt::CrossCursor);
m_grabbing = true; m_grabbing = true;
} else if (act == actClearCodeModelSnapshot) {
m_manager->clearCppCodeModelSnapshot();
} else { } else {
for (int i = 0; i != alternativeFormats.size(); ++i) { for (int i = 0; i != alternativeFormats.size(); ++i) {
if (act == typeFormatActions.at(i)) if (act == typeFormatActions.at(i))

View File

@@ -670,6 +670,7 @@ void S60DeviceRunControlBase::signsisProcessFinished()
} }
m_launcher = new trk::Launcher(); m_launcher = new trk::Launcher();
connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished())); 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(copyingStarted()), this, SLOT(printCopyingNotice()));
connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(printCreateFileFailed(QString,QString))); connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(printCreateFileFailed(QString,QString)));
connect(m_launcher, SIGNAL(canNotWriteFile(QString,QString)), this, SLOT(printWriteFileFailed(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)); 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() void S60DeviceRunControlBase::printCopyingNotice()
{ {
emit addToOutputWindow(this, tr("Copying install file...")); emit addToOutputWindow(this, tr("Copying install file..."));

View File

@@ -180,6 +180,7 @@ private slots:
void makesisProcessFinished(); void makesisProcessFinished();
void signsisProcessFailed(); void signsisProcessFailed();
void signsisProcessFinished(); void signsisProcessFinished();
void printConnectFailed(const QString &errorMessage);
void printCopyingNotice(); void printCopyingNotice();
void printCreateFileFailed(const QString &filename, const QString &errorMessage); void printCreateFileFailed(const QString &filename, const QString &errorMessage);
void printWriteFileFailed(const QString &filename, const QString &errorMessage); void printWriteFileFailed(const QString &filename, const QString &errorMessage);

View File

@@ -54,7 +54,7 @@
#include <cstddef> #include <cstddef>
#include <algorithm> #include <algorithm>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
AST::AST() AST::AST()
{ } { }
@@ -2493,4 +2493,4 @@ unsigned ObjCSynchronizedStatementAST::lastToken() const
return synchronized_token + 1; return synchronized_token + 1;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -53,8 +53,8 @@
#include "ASTfwd.h" #include "ASTfwd.h"
#include "MemoryPool.h" #include "MemoryPool.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
template <typename _Tp> template <typename _Tp>
class List: public Managed class List: public Managed
@@ -3168,7 +3168,7 @@ protected:
virtual void accept0(ASTVisitor *visitor); virtual void accept0(ASTVisitor *visitor);
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_AST_H #endif // CPLUSPLUS_AST_H

View File

@@ -30,7 +30,7 @@
#include "AST.h" #include "AST.h"
#include "ASTVisitor.h" #include "ASTVisitor.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const
{ {
@@ -986,7 +986,9 @@ SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
// copy ExpressionAST // copy ExpressionAST
// copy SizeofExpressionAST // copy SizeofExpressionAST
ast->sizeof_token = sizeof_token; ast->sizeof_token = sizeof_token;
ast->lparen_token = lparen_token;
if (expression) ast->expression = expression->clone(pool); if (expression) ast->expression = expression->clone(pool);
ast->rparen_token = rparen_token;
return ast; return ast;
} }
@@ -1207,7 +1209,7 @@ IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const
{ {
IdentifierListAST *ast = new (pool) IdentifierListAST; IdentifierListAST *ast = new (pool) IdentifierListAST;
// copy IdentifierListAST // copy IdentifierListAST
if (ast->name) ast->name = name->clone(pool); if (name) ast->name = name->clone(pool);
ast->comma_token = comma_token; ast->comma_token = comma_token;
if (next) ast->next = next->clone(pool); if (next) ast->next = next->clone(pool);
return ast; return ast;
@@ -1249,9 +1251,11 @@ ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const
ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclarationAST::clone(MemoryPool *pool) const ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCProtocolForwardDeclarationAST *ast = new (pool) ObjCProtocolForwardDeclarationAST; ObjCProtocolForwardDeclarationAST *ast = new (pool) ObjCProtocolForwardDeclarationAST;
// copy DeclarationAST
// copy ObjCProtocolForwardDeclarationAST
if (attributes) ast->attributes = attributes->clone(pool); if (attributes) ast->attributes = attributes->clone(pool);
ast->protocol_token = protocol_token; 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; ast->semicolon_token = semicolon_token;
return ast; return ast;
} }
@@ -1259,6 +1263,8 @@ ObjCProtocolForwardDeclarationAST *ObjCProtocolForwardDeclarationAST::clone(Memo
ObjCProtocolDeclarationAST *ObjCProtocolDeclarationAST::clone(MemoryPool *pool) const ObjCProtocolDeclarationAST *ObjCProtocolDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCProtocolDeclarationAST *ast = new (pool) ObjCProtocolDeclarationAST; ObjCProtocolDeclarationAST *ast = new (pool) ObjCProtocolDeclarationAST;
// copy DeclarationAST
// copy ObjCProtocolDeclarationAST
if (attributes) ast->attributes = attributes->clone(pool); if (attributes) ast->attributes = attributes->clone(pool);
ast->protocol_token = protocol_token; ast->protocol_token = protocol_token;
if (name) ast->name = name->clone(pool); if (name) ast->name = name->clone(pool);
@@ -1271,15 +1277,35 @@ ObjCProtocolDeclarationAST *ObjCProtocolDeclarationAST::clone(MemoryPool *pool)
ObjCProtocolRefsAST *ObjCProtocolRefsAST::clone(MemoryPool *pool) const ObjCProtocolRefsAST *ObjCProtocolRefsAST::clone(MemoryPool *pool) const
{ {
ObjCProtocolRefsAST *ast = new (pool) ObjCProtocolRefsAST; ObjCProtocolRefsAST *ast = new (pool) ObjCProtocolRefsAST;
// copy ObjCProtocolRefsAST
ast->less_token = less_token; 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; ast->greater_token = greater_token;
return ast; 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 *ObjCMessageExpressionAST::clone(MemoryPool *pool) const
{ {
ObjCMessageExpressionAST *ast = new (pool) ObjCMessageExpressionAST; ObjCMessageExpressionAST *ast = new (pool) ObjCMessageExpressionAST;
// copy ExpressionAST
// copy ObjCMessageExpressionAST
ast->lbracket_token = lbracket_token; ast->lbracket_token = lbracket_token;
if (receiver_expression) ast->receiver_expression = receiver_expression->clone(pool); if (receiver_expression) ast->receiver_expression = receiver_expression->clone(pool);
if (selector) ast->selector = selector->clone(pool); if (selector) ast->selector = selector->clone(pool);
@@ -1288,24 +1314,11 @@ ObjCMessageExpressionAST *ObjCMessageExpressionAST::clone(MemoryPool *pool) cons
return ast; 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 *ObjCProtocolExpressionAST::clone(MemoryPool *pool) const
{ {
ObjCProtocolExpressionAST *ast = new (pool) ObjCProtocolExpressionAST; ObjCProtocolExpressionAST *ast = new (pool) ObjCProtocolExpressionAST;
// copy ExpressionAST
// copy ObjCProtocolExpressionAST
ast->protocol_token = protocol_token; ast->protocol_token = protocol_token;
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
ast->identifier_token = identifier_token; ast->identifier_token = identifier_token;
@@ -1316,8 +1329,8 @@ ObjCProtocolExpressionAST *ObjCProtocolExpressionAST::clone(MemoryPool *pool) co
ObjCTypeNameAST *ObjCTypeNameAST::clone(MemoryPool *pool) const ObjCTypeNameAST *ObjCTypeNameAST::clone(MemoryPool *pool) const
{ {
ObjCTypeNameAST *ast = new (pool) ObjCTypeNameAST; ObjCTypeNameAST *ast = new (pool) ObjCTypeNameAST;
// copy ObjCTypeNameAST
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
ast->type_qualifier = type_qualifier;
if (type_id) ast->type_id = type_id->clone(pool); if (type_id) ast->type_id = type_id->clone(pool);
ast->rparen_token = rparen_token; ast->rparen_token = rparen_token;
return ast; return ast;
@@ -1326,6 +1339,8 @@ ObjCTypeNameAST *ObjCTypeNameAST::clone(MemoryPool *pool) const
ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
{ {
ObjCEncodeExpressionAST *ast = new (pool) ObjCEncodeExpressionAST; ObjCEncodeExpressionAST *ast = new (pool) ObjCEncodeExpressionAST;
// copy ExpressionAST
// copy ObjCEncodeExpressionAST
ast->encode_token = encode_token; ast->encode_token = encode_token;
if (type_name) ast->type_name = type_name->clone(pool); if (type_name) ast->type_name = type_name->clone(pool);
return ast; return ast;
@@ -1334,6 +1349,8 @@ ObjCEncodeExpressionAST *ObjCEncodeExpressionAST::clone(MemoryPool *pool) const
ObjCSelectorWithoutArgumentsAST *ObjCSelectorWithoutArgumentsAST::clone(MemoryPool *pool) const ObjCSelectorWithoutArgumentsAST *ObjCSelectorWithoutArgumentsAST::clone(MemoryPool *pool) const
{ {
ObjCSelectorWithoutArgumentsAST *ast = new (pool) ObjCSelectorWithoutArgumentsAST; ObjCSelectorWithoutArgumentsAST *ast = new (pool) ObjCSelectorWithoutArgumentsAST;
// copy ObjCSelectorAST
// copy ObjCSelectorWithoutArgumentsAST
ast->name_token = name_token; ast->name_token = name_token;
return ast; return ast;
} }
@@ -1341,6 +1358,7 @@ ObjCSelectorWithoutArgumentsAST *ObjCSelectorWithoutArgumentsAST::clone(MemoryPo
ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const
{ {
ObjCSelectorArgumentAST *ast = new (pool) ObjCSelectorArgumentAST; ObjCSelectorArgumentAST *ast = new (pool) ObjCSelectorArgumentAST;
// copy ObjCSelectorArgumentAST
ast->name_token = name_token; ast->name_token = name_token;
ast->colon_token = colon_token; ast->colon_token = colon_token;
return ast; return ast;
@@ -1349,6 +1367,7 @@ ObjCSelectorArgumentAST *ObjCSelectorArgumentAST::clone(MemoryPool *pool) const
ObjCSelectorArgumentListAST *ObjCSelectorArgumentListAST::clone(MemoryPool *pool) const ObjCSelectorArgumentListAST *ObjCSelectorArgumentListAST::clone(MemoryPool *pool) const
{ {
ObjCSelectorArgumentListAST *ast = new (pool) ObjCSelectorArgumentListAST; ObjCSelectorArgumentListAST *ast = new (pool) ObjCSelectorArgumentListAST;
// copy ObjCSelectorArgumentListAST
if (argument) ast->argument = argument->clone(pool); if (argument) ast->argument = argument->clone(pool);
if (next) ast->next = next->clone(pool); if (next) ast->next = next->clone(pool);
return ast; return ast;
@@ -1357,6 +1376,8 @@ ObjCSelectorArgumentListAST *ObjCSelectorArgumentListAST::clone(MemoryPool *pool
ObjCSelectorWithArgumentsAST *ObjCSelectorWithArgumentsAST::clone(MemoryPool *pool) const ObjCSelectorWithArgumentsAST *ObjCSelectorWithArgumentsAST::clone(MemoryPool *pool) const
{ {
ObjCSelectorWithArgumentsAST *ast = new (pool) ObjCSelectorWithArgumentsAST; ObjCSelectorWithArgumentsAST *ast = new (pool) ObjCSelectorWithArgumentsAST;
// copy ObjCSelectorAST
// copy ObjCSelectorWithArgumentsAST
if (selector_arguments) ast->selector_arguments = selector_arguments->clone(pool); if (selector_arguments) ast->selector_arguments = selector_arguments->clone(pool);
return ast; return ast;
} }
@@ -1364,6 +1385,8 @@ ObjCSelectorWithArgumentsAST *ObjCSelectorWithArgumentsAST::clone(MemoryPool *po
ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) const ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) const
{ {
ObjCSelectorExpressionAST *ast = new (pool) ObjCSelectorExpressionAST; ObjCSelectorExpressionAST *ast = new (pool) ObjCSelectorExpressionAST;
// copy ExpressionAST
// copy ObjCSelectorExpressionAST
ast->selector_token = selector_token; ast->selector_token = selector_token;
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
if (selector) ast->selector = selector->clone(pool); if (selector) ast->selector = selector->clone(pool);
@@ -1374,6 +1397,7 @@ ObjCSelectorExpressionAST *ObjCSelectorExpressionAST::clone(MemoryPool *pool) co
ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(MemoryPool *pool) const ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCInstanceVariablesDeclarationAST *ast = new (pool) ObjCInstanceVariablesDeclarationAST; ObjCInstanceVariablesDeclarationAST *ast = new (pool) ObjCInstanceVariablesDeclarationAST;
// copy ObjCInstanceVariablesDeclarationAST
ast->lbrace_token = lbrace_token; ast->lbrace_token = lbrace_token;
if (instance_variables) ast->instance_variables = instance_variables->clone(pool); if (instance_variables) ast->instance_variables = instance_variables->clone(pool);
ast->rbrace_token = rbrace_token; ast->rbrace_token = rbrace_token;
@@ -1383,6 +1407,8 @@ ObjCInstanceVariablesDeclarationAST *ObjCInstanceVariablesDeclarationAST::clone(
ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *pool) const ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCVisibilityDeclarationAST *ast = new (pool) ObjCVisibilityDeclarationAST; ObjCVisibilityDeclarationAST *ast = new (pool) ObjCVisibilityDeclarationAST;
// copy DeclarationAST
// copy ObjCVisibilityDeclarationAST
ast->visibility_token = visibility_token; ast->visibility_token = visibility_token;
return ast; return ast;
} }
@@ -1390,6 +1416,7 @@ ObjCVisibilityDeclarationAST *ObjCVisibilityDeclarationAST::clone(MemoryPool *po
ObjCPropertyAttributeAST *ObjCPropertyAttributeAST::clone(MemoryPool *pool) const ObjCPropertyAttributeAST *ObjCPropertyAttributeAST::clone(MemoryPool *pool) const
{ {
ObjCPropertyAttributeAST *ast = new (pool) ObjCPropertyAttributeAST; ObjCPropertyAttributeAST *ast = new (pool) ObjCPropertyAttributeAST;
// copy ObjCPropertyAttributeAST
ast->attribute_identifier_token = attribute_identifier_token; ast->attribute_identifier_token = attribute_identifier_token;
ast->equals_token = equals_token; ast->equals_token = equals_token;
if (method_selector) ast->method_selector = method_selector->clone(pool); 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 *ObjCPropertyAttributeListAST::clone(MemoryPool *pool) const
{ {
ObjCPropertyAttributeListAST *ast = new (pool) ObjCPropertyAttributeListAST; ObjCPropertyAttributeListAST *ast = new (pool) ObjCPropertyAttributeListAST;
// copy ObjCPropertyAttributeListAST
if (attr) ast->attr = attr->clone(pool); if (attr) ast->attr = attr->clone(pool);
ast->comma_token = comma_token; ast->comma_token = comma_token;
if (next) ast->next = next->clone(pool); if (next) ast->next = next->clone(pool);
@@ -1408,6 +1436,8 @@ ObjCPropertyAttributeListAST *ObjCPropertyAttributeListAST::clone(MemoryPool *po
ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool) const ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCPropertyDeclarationAST *ast = new (pool) ObjCPropertyDeclarationAST; ObjCPropertyDeclarationAST *ast = new (pool) ObjCPropertyDeclarationAST;
// copy DeclarationAST
// copy ObjCPropertyDeclarationAST
if (attributes) ast->attributes = attributes->clone(pool); if (attributes) ast->attributes = attributes->clone(pool);
ast->property_token = property_token; ast->property_token = property_token;
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
@@ -1420,6 +1450,9 @@ ObjCPropertyDeclarationAST *ObjCPropertyDeclarationAST::clone(MemoryPool *pool)
ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(MemoryPool *pool) const ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCMessageArgumentDeclarationAST *ast = new (pool) ObjCMessageArgumentDeclarationAST; ObjCMessageArgumentDeclarationAST *ast = new (pool) ObjCMessageArgumentDeclarationAST;
// copy ExpressionAST
// copy NameAST
// copy ObjCMessageArgumentDeclarationAST
if (type_name) ast->type_name = type_name->clone(pool); if (type_name) ast->type_name = type_name->clone(pool);
if (attributes) ast->attributes = attributes->clone(pool); if (attributes) ast->attributes = attributes->clone(pool);
ast->param_name_token = param_name_token; ast->param_name_token = param_name_token;
@@ -1429,6 +1462,7 @@ ObjCMessageArgumentDeclarationAST *ObjCMessageArgumentDeclarationAST::clone(Memo
ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationListAST::clone(MemoryPool *pool) const ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationListAST::clone(MemoryPool *pool) const
{ {
ObjCMessageArgumentDeclarationListAST *ast = new (pool) ObjCMessageArgumentDeclarationListAST; ObjCMessageArgumentDeclarationListAST *ast = new (pool) ObjCMessageArgumentDeclarationListAST;
// copy ObjCMessageArgumentDeclarationListAST
if (argument_declaration) ast->argument_declaration = argument_declaration->clone(pool); if (argument_declaration) ast->argument_declaration = argument_declaration->clone(pool);
if (next) ast->next = next->clone(pool); if (next) ast->next = next->clone(pool);
return ast; return ast;
@@ -1437,9 +1471,12 @@ ObjCMessageArgumentDeclarationListAST *ObjCMessageArgumentDeclarationListAST::cl
ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
{ {
ObjCMethodPrototypeAST *ast = new (pool) ObjCMethodPrototypeAST; ObjCMethodPrototypeAST *ast = new (pool) ObjCMethodPrototypeAST;
// copy ObjCMethodPrototypeAST
ast->method_type_token = method_type_token; ast->method_type_token = method_type_token;
if (type_name) ast->type_name = type_name->clone(pool); if (type_name) ast->type_name = type_name->clone(pool);
if (selector) ast->selector = selector->clone(pool);
if (arguments) ast->arguments = arguments->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); if (attributes) ast->attributes = attributes->clone(pool);
return ast; return ast;
} }
@@ -1447,6 +1484,8 @@ ObjCMethodPrototypeAST *ObjCMethodPrototypeAST::clone(MemoryPool *pool) const
ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) const ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCMethodDeclarationAST *ast = new (pool) ObjCMethodDeclarationAST; ObjCMethodDeclarationAST *ast = new (pool) ObjCMethodDeclarationAST;
// copy DeclarationAST
// copy ObjCMethodDeclarationAST
if (method_prototype) ast->method_prototype = method_prototype->clone(pool); if (method_prototype) ast->method_prototype = method_prototype->clone(pool);
if (function_body) ast->function_body = function_body->clone(pool); if (function_body) ast->function_body = function_body->clone(pool);
ast->semicolon_token = semicolon_token; ast->semicolon_token = semicolon_token;
@@ -1456,15 +1495,15 @@ ObjCMethodDeclarationAST *ObjCMethodDeclarationAST::clone(MemoryPool *pool) cons
ObjCSynthesizedPropertyAST *ObjCSynthesizedPropertyAST::clone(MemoryPool *pool) const ObjCSynthesizedPropertyAST *ObjCSynthesizedPropertyAST::clone(MemoryPool *pool) const
{ {
ObjCSynthesizedPropertyAST *ast = new (pool) ObjCSynthesizedPropertyAST; ObjCSynthesizedPropertyAST *ast = new (pool) ObjCSynthesizedPropertyAST;
ast->property_identifier = property_identifier; // copy ObjCSynthesizedPropertyAST
ast->equals_token = equals_token; ast->equals_token = equals_token;
ast->property_alias_identifier = property_alias_identifier;
return ast; return ast;
} }
ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyListAST::clone(MemoryPool *pool) const ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyListAST::clone(MemoryPool *pool) const
{ {
ObjCSynthesizedPropertyListAST *ast = new (pool) ObjCSynthesizedPropertyListAST; ObjCSynthesizedPropertyListAST *ast = new (pool) ObjCSynthesizedPropertyListAST;
// copy ObjCSynthesizedPropertyListAST
if (synthesized_property) ast->synthesized_property = synthesized_property->clone(pool); if (synthesized_property) ast->synthesized_property = synthesized_property->clone(pool);
ast->comma_token = comma_token; ast->comma_token = comma_token;
if (next) ast->next = next->clone(pool); if (next) ast->next = next->clone(pool);
@@ -1474,6 +1513,8 @@ ObjCSynthesizedPropertyListAST *ObjCSynthesizedPropertyListAST::clone(MemoryPool
ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST::clone(MemoryPool *pool) const ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCSynthesizedPropertiesDeclarationAST *ast = new (pool) ObjCSynthesizedPropertiesDeclarationAST; ObjCSynthesizedPropertiesDeclarationAST *ast = new (pool) ObjCSynthesizedPropertiesDeclarationAST;
// copy DeclarationAST
// copy ObjCSynthesizedPropertiesDeclarationAST
ast->synthesized_token = synthesized_token; ast->synthesized_token = synthesized_token;
if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool); if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool);
ast->semicolon_token = semicolon_token; ast->semicolon_token = semicolon_token;
@@ -1483,6 +1524,8 @@ ObjCSynthesizedPropertiesDeclarationAST *ObjCSynthesizedPropertiesDeclarationAST
ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(MemoryPool *pool) const ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(MemoryPool *pool) const
{ {
ObjCDynamicPropertiesDeclarationAST *ast = new (pool) ObjCDynamicPropertiesDeclarationAST; ObjCDynamicPropertiesDeclarationAST *ast = new (pool) ObjCDynamicPropertiesDeclarationAST;
// copy DeclarationAST
// copy ObjCDynamicPropertiesDeclarationAST
ast->dynamic_token = dynamic_token; ast->dynamic_token = dynamic_token;
if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool); if (property_identifiers) ast->property_identifiers = property_identifiers->clone(pool);
ast->semicolon_token = semicolon_token; ast->semicolon_token = semicolon_token;
@@ -1492,6 +1535,8 @@ ObjCDynamicPropertiesDeclarationAST *ObjCDynamicPropertiesDeclarationAST::clone(
ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const ObjCFastEnumerationAST *ObjCFastEnumerationAST::clone(MemoryPool *pool) const
{ {
ObjCFastEnumerationAST *ast = new (pool) ObjCFastEnumerationAST; ObjCFastEnumerationAST *ast = new (pool) ObjCFastEnumerationAST;
// copy StatementAST
// copy ObjCFastEnumerationAST
ast->for_token = for_token; ast->for_token = for_token;
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
if (type_specifiers) ast->type_specifiers = type_specifiers->clone(pool); 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 *ObjCSynchronizedStatementAST::clone(MemoryPool *pool) const
{ {
ObjCSynchronizedStatementAST *ast = new (pool) ObjCSynchronizedStatementAST; ObjCSynchronizedStatementAST *ast = new (pool) ObjCSynchronizedStatementAST;
// copy StatementAST
// copy ObjCSynchronizedStatementAST
ast->synchronized_token = synchronized_token; ast->synchronized_token = synchronized_token;
ast->lparen_token = lparen_token; ast->lparen_token = lparen_token;
if (synchronized_object) ast->synchronized_object = synchronized_object->clone(pool); 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); if (statement) ast->statement = statement->clone(pool);
return ast; return ast;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -30,7 +30,7 @@
#include "AST.h" #include "AST.h"
#include "ASTVisitor.h" #include "ASTVisitor.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
void SimpleSpecifierAST::accept0(ASTVisitor *visitor) void SimpleSpecifierAST::accept0(ASTVisitor *visitor)
{ {
@@ -1465,4 +1465,4 @@ void ObjCSynchronizedStatementAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this); visitor->endVisit(this);
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -51,7 +51,7 @@
#include "TranslationUnit.h" #include "TranslationUnit.h"
#include "Control.h" #include "Control.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
ASTVisitor::ASTVisitor(Control *control) ASTVisitor::ASTVisitor(Control *control)
: _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 void ASTVisitor::getTokenEndPosition(unsigned index, unsigned *line, unsigned *column) const
{ getPosition(tokenAt(index).end(), line, column); } { getPosition(tokenAt(index).end(), line, column); }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "ASTfwd.h" #include "ASTfwd.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT ASTVisitor class CPLUSPLUS_EXPORT ASTVisitor
{ {
@@ -371,7 +371,7 @@ private:
Control *_control; Control *_control;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_ASTVISITOR_H #endif // CPLUSPLUS_ASTVISITOR_H

View File

@@ -51,8 +51,8 @@
#include <CPlusPlusForwardDeclarations.h> #include <CPlusPlusForwardDeclarations.h>
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class AST; class AST;
class ASTVisitor; class ASTVisitor;
@@ -203,7 +203,7 @@ class ObjCDynamicPropertiesDeclarationAST;
class ObjCFastEnumerationAST; class ObjCFastEnumerationAST;
class ObjCSynchronizedStatementAST; class ObjCSynchronizedStatementAST;
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_ASTFWD_H #endif // CPLUSPLUS_ASTFWD_H

View File

@@ -53,8 +53,8 @@
#include <new> #include <new>
#include <cstdlib> #include <cstdlib>
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
template <typename _Tp, int SEGMENT_SHIFT = 4> template <typename _Tp, int SEGMENT_SHIFT = 4>
class Array class Array
@@ -125,7 +125,7 @@ private:
int _count; int _count;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_ARRAY_H #endif // CPLUSPLUS_ARRAY_H

View File

@@ -49,34 +49,19 @@
#ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
#define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H
#ifndef CPLUSPLUS_WITH_NO_QT #ifndef CPLUSPLUS_WITHOUT_QT
# include <QtCore/qglobal.h> # include <QtCore/qglobal.h>
# define CPLUSPLUS_BEGIN_HEADER
# define CPLUSPLUS_END_HEADER
# if defined(CPLUSPLUS_BUILD_LIB) # if defined(CPLUSPLUS_BUILD_LIB)
# define CPLUSPLUS_EXPORT Q_DECL_EXPORT # define CPLUSPLUS_EXPORT Q_DECL_EXPORT
# else # else
# define CPLUSPLUS_EXPORT Q_DECL_IMPORT # define CPLUSPLUS_EXPORT Q_DECL_IMPORT
# endif # endif
# define CPLUSPLUS_WITH_NAMESPACE
#else #else
# define CPLUSPLUS_BEGIN_HEADER
# define CPLUSPLUS_END_HEADER
# define CPLUSPLUS_EXPORT # define CPLUSPLUS_EXPORT
#endif #endif
#ifdef CPLUSPLUS_WITH_NAMESPACE namespace CPlusPlus {
# 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
class TranslationUnit; class TranslationUnit;
class Semantic; class Semantic;
@@ -144,7 +129,6 @@ class ObjCProtocol;
class ObjCForwardProtocolDeclaration; class ObjCForwardProtocolDeclaration;
class ObjCMethod; class ObjCMethod;
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H

View File

@@ -57,9 +57,8 @@
#include "Control.h" #include "Control.h"
#include "Literals.h" #include "Literals.h"
#include <cassert> #include <cassert>
#include <QtCore/QByteArray>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
CheckDeclaration::CheckDeclaration(Semantic *semantic) CheckDeclaration::CheckDeclaration(Semantic *semantic)
: SemanticCheck(semantic), : SemanticCheck(semantic),
@@ -228,7 +227,6 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast)
if (it->declarator && it->declarator->initializer) { if (it->declarator && it->declarator->initializer) {
FullySpecifiedType initTy = semantic()->check(it->declarator->initializer, _scope); FullySpecifiedType initTy = semantic()->check(it->declarator->initializer, _scope);
Q_UNUSED(initTy)
} }
*decl_it = new (translationUnit()->memoryPool()) List<Declaration *>(); *decl_it = new (translationUnit()->memoryPool()) List<Declaration *>();
@@ -702,26 +700,26 @@ bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
if (!attrAst) if (!attrAst)
continue; continue;
const char *attrName = spell(attrAst->attribute_identifier_token); Identifier *attrId = identifier(attrAst->attribute_identifier_token);
if (!qstrcmp("getter", attrName)) { if (attrId == control()->objcGetterId()) {
if (checkPropertyAttribute(attrAst, propAttrs, Getter)) { if (checkPropertyAttribute(attrAst, propAttrs, Getter)) {
// TODO: find method declaration for getter // TODO: find method declaration for getter
} }
} else if (!qstrcmp("setter", attrName)) { } else if (attrId == control()->objcSetterId()) {
if (checkPropertyAttribute(attrAst, propAttrs, Setter)) { if (checkPropertyAttribute(attrAst, propAttrs, Setter)) {
// TODO: find method declaration for setter // TODO: find method declaration for setter
} }
} else if (!qstrcmp("readwrite", attrName)) { } else if (attrId == control()->objcReadwriteId()) {
checkPropertyAttribute(attrAst, propAttrs, ReadWrite); checkPropertyAttribute(attrAst, propAttrs, ReadWrite);
} else if (!qstrcmp("readonly", attrName)) { } else if (attrId == control()->objcReadonlyId()) {
checkPropertyAttribute(attrAst, propAttrs, ReadOnly); checkPropertyAttribute(attrAst, propAttrs, ReadOnly);
} else if (!qstrcmp("assign", attrName)) { } else if (attrId == control()->objcAssignId()) {
checkPropertyAttribute(attrAst, propAttrs, Assign); checkPropertyAttribute(attrAst, propAttrs, Assign);
} else if (!qstrcmp("retain", attrName)) { } else if (attrId == control()->objcRetainId()) {
checkPropertyAttribute(attrAst, propAttrs, Retain); checkPropertyAttribute(attrAst, propAttrs, Retain);
} else if (!qstrcmp("copy", attrName)) { } else if (attrId == control()->objcCopyId()) {
checkPropertyAttribute(attrAst, propAttrs, Copy); checkPropertyAttribute(attrAst, propAttrs, Copy);
} else if (!qstrcmp("nonatomic", attrName)) { } else if (attrId == control()->objcNonatomicId()) {
checkPropertyAttribute(attrAst, propAttrs, NonAtomic); checkPropertyAttribute(attrAst, propAttrs, NonAtomic);
} }
} }
@@ -745,4 +743,4 @@ bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
return false; return false;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "SemanticCheck.h" #include "SemanticCheck.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckDeclaration: public SemanticCheck class CPLUSPLUS_EXPORT CheckDeclaration: public SemanticCheck
{ {
@@ -111,7 +111,7 @@ private:
bool _checkAnonymousArguments: 1; bool _checkAnonymousArguments: 1;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CHECKDECLARATION_H #endif // CPLUSPLUS_CHECKDECLARATION_H

View File

@@ -55,7 +55,7 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Symbols.h" #include "Symbols.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
CheckDeclarator::CheckDeclarator(Semantic *semantic) CheckDeclarator::CheckDeclarator(Semantic *semantic)
: SemanticCheck(semantic), : SemanticCheck(semantic),
@@ -300,4 +300,4 @@ void CheckDeclarator::applyCvQualifiers(SpecifierAST *cv)
} }
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -53,8 +53,8 @@
#include "SemanticCheck.h" #include "SemanticCheck.h"
#include "FullySpecifiedType.h" #include "FullySpecifiedType.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckDeclarator: public SemanticCheck class CPLUSPLUS_EXPORT CheckDeclarator: public SemanticCheck
{ {
@@ -106,7 +106,7 @@ private:
FullySpecifiedType _fullySpecifiedType; FullySpecifiedType _fullySpecifiedType;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CHECKDECLARATOR_H #endif // CPLUSPLUS_CHECKDECLARATOR_H

View File

@@ -56,7 +56,7 @@
#include "Symbols.h" #include "Symbols.h"
#include "Control.h" #include "Control.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
CheckExpression::CheckExpression(Semantic *semantic) CheckExpression::CheckExpression(Semantic *semantic)
: SemanticCheck(semantic), : SemanticCheck(semantic),
@@ -207,7 +207,6 @@ bool CheckExpression::visit(NewExpressionAST *ast)
if (ast->new_placement) { if (ast->new_placement) {
for (ExpressionListAST *it = ast->new_placement->expression_list; it; it = it->next) { for (ExpressionListAST *it = ast->new_placement->expression_list; it; it = it->next) {
FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
Q_UNUSED(exprTy)
} }
} }
@@ -215,18 +214,15 @@ bool CheckExpression::visit(NewExpressionAST *ast)
if (ast->new_type_id) { if (ast->new_type_id) {
FullySpecifiedType ty = semantic()->check(ast->new_type_id->type_specifier, _scope); 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) { for (NewArrayDeclaratorAST *it = ast->new_type_id->new_array_declarators; it; it = it->next) {
FullySpecifiedType exprTy = semantic()->check(it->expression, _scope); FullySpecifiedType exprTy = semantic()->check(it->expression, _scope);
Q_UNUSED(exprTy)
} }
} }
// ### process new-initializer // ### process new-initializer
if (ast->new_initializer) { if (ast->new_initializer) {
FullySpecifiedType exprTy = semantic()->check(ast->new_initializer->expression, _scope); FullySpecifiedType exprTy = semantic()->check(ast->new_initializer->expression, _scope);
Q_UNUSED(exprTy)
} }
return false; return false;
@@ -397,4 +393,4 @@ bool CheckExpression::visit(ObjCSelectorExpressionAST *ast)
return false; return false;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -53,8 +53,8 @@
#include "SemanticCheck.h" #include "SemanticCheck.h"
#include "FullySpecifiedType.h" #include "FullySpecifiedType.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckExpression: public SemanticCheck class CPLUSPLUS_EXPORT CheckExpression: public SemanticCheck
{ {
@@ -122,7 +122,7 @@ private:
bool _checkOldStyleCasts: 1; bool _checkOldStyleCasts: 1;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CHECKEXPRESSION_H #endif // CPLUSPLUS_CHECKEXPRESSION_H

View File

@@ -58,7 +58,7 @@
#include "Scope.h" #include "Scope.h"
#include <cassert> #include <cassert>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
CheckName::CheckName(Semantic *semantic) CheckName::CheckName(Semantic *semantic)
: SemanticCheck(semantic), : SemanticCheck(semantic),
@@ -425,4 +425,4 @@ bool CheckName::visit(ObjCMessageArgumentDeclarationAST *ast)
return false; return false;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "SemanticCheck.h" #include "SemanticCheck.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckName: public SemanticCheck class CPLUSPLUS_EXPORT CheckName: public SemanticCheck
{ {
@@ -89,7 +89,7 @@ private:
Scope *_scope; Scope *_scope;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CHECKNAME_H #endif // CPLUSPLUS_CHECKNAME_H

View File

@@ -58,7 +58,7 @@
#include "Control.h" #include "Control.h"
#include "Scope.h" #include "Scope.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
CheckSpecifier::CheckSpecifier(Semantic *semantic) CheckSpecifier::CheckSpecifier(Semantic *semantic)
: SemanticCheck(semantic), : SemanticCheck(semantic),
@@ -420,4 +420,4 @@ bool CheckSpecifier::visit(ObjCTypeNameAST * /*ast*/)
return true; return true;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -53,8 +53,8 @@
#include "SemanticCheck.h" #include "SemanticCheck.h"
#include "FullySpecifiedType.h" #include "FullySpecifiedType.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckSpecifier: public SemanticCheck class CPLUSPLUS_EXPORT CheckSpecifier: public SemanticCheck
{ {
@@ -88,7 +88,7 @@ private:
Scope *_scope; Scope *_scope;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CHECKSPECIFIER_H #endif // CPLUSPLUS_CHECKSPECIFIER_H

View File

@@ -55,7 +55,7 @@
#include "Control.h" #include "Control.h"
#include "Symbols.h" #include "Symbols.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
CheckStatement::CheckStatement(Semantic *semantic) CheckStatement::CheckStatement(Semantic *semantic)
: SemanticCheck(semantic), : SemanticCheck(semantic),
@@ -307,4 +307,4 @@ bool CheckStatement::visit(WhileStatementAST *ast)
return false; return false;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "SemanticCheck.h" #include "SemanticCheck.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT CheckStatement: public SemanticCheck class CPLUSPLUS_EXPORT CheckStatement: public SemanticCheck
{ {
@@ -94,7 +94,7 @@ private:
Scope *_scope; Scope *_scope;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CHECKSTATEMENT_H #endif // CPLUSPLUS_CHECKSTATEMENT_H

View File

@@ -57,7 +57,7 @@
#include <map> // ### replace me with LiteralTable #include <map> // ### replace me with LiteralTable
#include <string> #include <string>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
template <typename _Iterator> template <typename _Iterator>
@@ -89,7 +89,7 @@ public:
: control(control), : control(control),
translationUnit(0), translationUnit(0),
diagnosticClient(0) diagnosticClient(0)
{ } {}
~Data() ~Data()
{ {
@@ -577,10 +577,31 @@ public:
std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations; std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations; std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations;
std::vector<ObjCMethod *> objcMethods; 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() 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() Control::~Control()
{ delete d; } { delete d; }
@@ -766,4 +787,26 @@ ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsig
ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, Name *name) ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, Name *name)
{ return d->newObjCMethod(sourceLocation, 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; }

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include <cstddef> #include <cstddef>
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Control class CPLUSPLUS_EXPORT Control
{ {
@@ -169,6 +169,16 @@ public:
/// Creates a new Objective-C method symbol. /// Creates a new Objective-C method symbol.
ObjCMethod *newObjCMethod(unsigned sourceLocation, Name *name = 0); 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 *findIdentifier(const char *chars, unsigned size) const;
Identifier *findOrInsertIdentifier(const char *chars, unsigned size); Identifier *findOrInsertIdentifier(const char *chars, unsigned size);
@@ -199,7 +209,7 @@ private:
Data *d; Data *d;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CONTROL_H #endif // CPLUSPLUS_CONTROL_H

View File

@@ -51,7 +51,7 @@
#include "Names.h" #include "Names.h"
#include <algorithm> #include <algorithm>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
bool VoidType::isEqualTo(const Type *other) const bool VoidType::isEqualTo(const Type *other) const
@@ -230,4 +230,4 @@ bool NamedType::isEqualTo(const Type *other) const
void NamedType::accept0(TypeVisitor *visitor) void NamedType::accept0(TypeVisitor *visitor)
{ visitor->visit(this); } { visitor->visit(this); }
CPLUSPLUS_END_NAMESPACE

View File

@@ -54,8 +54,8 @@
#include "FullySpecifiedType.h" #include "FullySpecifiedType.h"
#include <cstddef> #include <cstddef>
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT UndefinedType : public Type class CPLUSPLUS_EXPORT UndefinedType : public Type
{ {
@@ -272,7 +272,7 @@ private:
Name *_name; Name *_name;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_CORETYPES_H #endif // CPLUSPLUS_CORETYPES_H

View File

@@ -48,7 +48,7 @@
#include "DiagnosticClient.h" #include "DiagnosticClient.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
DiagnosticClient::DiagnosticClient() DiagnosticClient::DiagnosticClient()
{ } { }
@@ -56,4 +56,4 @@ DiagnosticClient::DiagnosticClient()
DiagnosticClient::~DiagnosticClient() DiagnosticClient::~DiagnosticClient()
{ } { }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "stdarg.h" #include "stdarg.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT DiagnosticClient class CPLUSPLUS_EXPORT DiagnosticClient
{ {
@@ -76,7 +76,7 @@ public:
const char *format, va_list ap) = 0; const char *format, va_list ap) = 0;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_DIAGNOSTICCLIENT_H #endif // CPLUSPLUS_DIAGNOSTICCLIENT_H

View File

@@ -50,7 +50,7 @@
#include "Type.h" #include "Type.h"
#include "CoreTypes.h" #include "CoreTypes.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
FullySpecifiedType::FullySpecifiedType(Type *type) : FullySpecifiedType::FullySpecifiedType(Type *type) :
_type(type), _flags(0) _type(type), _flags(0)
@@ -209,4 +209,4 @@ FullySpecifiedType FullySpecifiedType::simplified() const
return *this; return *this;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -51,8 +51,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT FullySpecifiedType class CPLUSPLUS_EXPORT FullySpecifiedType
{ {
@@ -151,7 +151,7 @@ private:
}; };
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_FULLYSPECIFIEDTYPE_H #endif // CPLUSPLUS_FULLYSPECIFIEDTYPE_H

View File

@@ -49,7 +49,7 @@
#include "Lexer.h" #include "Lexer.h"
#include "Token.h" #include "Token.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
static inline int classify2(const char *s, bool) { static inline int classify2(const char *s, bool) {
if (s[0] == 'd') { if (s[0] == 'd') {
@@ -1400,4 +1400,4 @@ int Lexer::classifyOperator(const char *s, int n) {
} // switch } // switch
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -55,7 +55,7 @@
using namespace std; using namespace std;
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
Lexer::Lexer(TranslationUnit *unit) Lexer::Lexer(TranslationUnit *unit)
: _translationUnit(unit), : _translationUnit(unit),
@@ -720,4 +720,4 @@ void Lexer::scan_helper(Token *tok)
} // switch } // switch
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "Token.h" #include "Token.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Lexer class CPLUSPLUS_EXPORT Lexer
{ {
@@ -152,7 +152,7 @@ private:
unsigned _currentLine; unsigned _currentLine;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_LEXER_H #endif // CPLUSPLUS_LEXER_H

View File

@@ -53,8 +53,8 @@
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
template <typename _Literal> template <typename _Literal>
class LiteralTable class LiteralTable
@@ -185,7 +185,7 @@ protected:
int _allocatedBuckets; int _allocatedBuckets;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_LITERALTABLE_H #endif // CPLUSPLUS_LITERALTABLE_H

View File

@@ -53,7 +53,7 @@
using namespace std; using namespace std;
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Literal::Literal(const char *chars, unsigned size) Literal::Literal(const char *chars, unsigned size)
@@ -227,4 +227,4 @@ bool Identifier::isEqualTo(const Identifier *other) const
return ! strcmp(chars(), other->chars()); return ! strcmp(chars(), other->chars());
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "Token.h" #include "Token.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Literal class CPLUSPLUS_EXPORT Literal
{ {
@@ -135,7 +135,7 @@ public:
bool isEqualTo(const Identifier *other) const; bool isEqualTo(const Identifier *other) const;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_LITERALS_H #endif // CPLUSPLUS_LITERALS_H

View File

@@ -51,7 +51,7 @@
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
using namespace std; using namespace std;
@@ -125,4 +125,4 @@ void Managed::operator delete(void *)
void Managed::operator delete(void *, MemoryPool *) void Managed::operator delete(void *, MemoryPool *)
{ } { }
CPLUSPLUS_END_NAMESPACE

View File

@@ -53,8 +53,8 @@
#include <cstddef> #include <cstddef>
#include <new> #include <new>
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT MemoryPool class CPLUSPLUS_EXPORT MemoryPool
{ {
@@ -110,7 +110,7 @@ public:
void operator delete(void *, MemoryPool *); void operator delete(void *, MemoryPool *);
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_MEMORYPOOL_H #endif // CPLUSPLUS_MEMORYPOOL_H

View File

@@ -50,7 +50,7 @@
#include "Names.h" #include "Names.h"
#include "NameVisitor.h" #include "NameVisitor.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
Name::Name() Name::Name()
{ } { }
@@ -93,4 +93,4 @@ void Name::accept(Name *name, NameVisitor *visitor)
name->accept(visitor); name->accept(visitor);
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -51,8 +51,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Name class CPLUSPLUS_EXPORT Name
{ {
@@ -98,7 +98,7 @@ protected:
virtual void accept0(NameVisitor *visitor) = 0; virtual void accept0(NameVisitor *visitor) = 0;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_NAME_H #endif // CPLUSPLUS_NAME_H

View File

@@ -49,7 +49,7 @@
#include "NameVisitor.h" #include "NameVisitor.h"
#include "Names.h" #include "Names.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
NameVisitor::NameVisitor() NameVisitor::NameVisitor()
{ } { }
@@ -60,4 +60,4 @@ NameVisitor::~NameVisitor()
void NameVisitor::accept(Name *name) void NameVisitor::accept(Name *name)
{ Name::accept(name, this); } { Name::accept(name, this); }
CPLUSPLUS_END_NAMESPACE

View File

@@ -51,8 +51,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT NameVisitor class CPLUSPLUS_EXPORT NameVisitor
{ {
@@ -77,7 +77,7 @@ public:
virtual void visit(SelectorNameId *) {} virtual void visit(SelectorNameId *) {}
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_NAMEVISITOR_H #endif // CPLUSPLUS_NAMEVISITOR_H

View File

@@ -52,7 +52,7 @@
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
QualifiedNameId::QualifiedNameId(Name *const names[], QualifiedNameId::QualifiedNameId(Name *const names[],
unsigned nameCount, unsigned nameCount,
@@ -326,4 +326,4 @@ bool SelectorNameId::isEqualTo(const Name *other) const
return true; return true;
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -53,8 +53,8 @@
#include "Name.h" #include "Name.h"
#include "FullySpecifiedType.h" #include "FullySpecifiedType.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT QualifiedNameId: public Name class CPLUSPLUS_EXPORT QualifiedNameId: public Name
{ {
@@ -304,7 +304,7 @@ private:
bool _hasArguments; bool _hasArguments;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_NAMES_H #endif // CPLUSPLUS_NAMES_H

View File

@@ -1,7 +1,7 @@
#include "Lexer.h" #include "Lexer.h"
#include "Token.h" #include "Token.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
static inline int classify3(const char *s) { static inline int classify3(const char *s) {
if (s[0] == 'e') { if (s[0] == 'e') {
@@ -461,4 +461,4 @@ int Lexer::classifyObjCAtKeyword(const char *s, int n) {
} // switch } // switch
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -29,7 +29,7 @@
#include "ObjectiveCTypeQualifiers.h" #include "ObjectiveCTypeQualifiers.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
static inline int classify2(const char *s) { static inline int classify2(const char *s) {
if (s[0] == 'N') { if (s[0] == 'N') {
@@ -315,7 +315,7 @@ static inline int classify9(const char *s) {
return Token_identifier; return Token_identifier;
} }
int classifyObjectiveCTypeQualifiers(const char *s, int n) { int CPlusPlus::classifyObjectiveCTypeQualifiers(const char *s, int n) {
switch (n) { switch (n) {
case 2: return classify2(s); case 2: return classify2(s);
case 3: return classify3(s); case 3: return classify3(s);
@@ -328,4 +328,4 @@ int classifyObjectiveCTypeQualifiers(const char *s, int n) {
} // switch } // switch
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -31,8 +31,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
enum { enum {
Token_NO, Token_NO,
@@ -65,7 +65,7 @@ enum {
CPLUSPLUS_EXPORT int classifyObjectiveCTypeQualifiers(const char *s, int n); CPLUSPLUS_EXPORT int classifyObjectiveCTypeQualifiers(const char *s, int n);
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_OBJC_TYPEQUALIFIERS_H #endif // CPLUSPLUS_OBJC_TYPEQUALIFIERS_H

File diff suppressed because it is too large Load Diff

View File

@@ -54,8 +54,8 @@
#include "Token.h" #include "Token.h"
#include "TranslationUnit.h" #include "TranslationUnit.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Parser class CPLUSPLUS_EXPORT Parser
{ {
@@ -264,8 +264,9 @@ public:
void match(int kind, unsigned *token); void match(int kind, unsigned *token);
bool maybeFunctionCall(SimpleDeclarationAST *simpleDecl) const; bool maybeAmbiguousStatement(DeclarationStatementAST *ast) const;
bool maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const; bool maybeForwardOrClassDeclaration(SpecifierAST *decl_specifier_seq) const;
bool isPointerDeclaration(DeclarationStatementAST *ast) const;
private: private:
bool switchTemplateArguments(bool templateArguments); bool switchTemplateArguments(bool templateArguments);
@@ -302,7 +303,7 @@ private:
void operator =(const Parser& source); void operator =(const Parser& source);
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_PARSER_H #endif // CPLUSPLUS_PARSER_H

View File

@@ -57,7 +57,7 @@
using namespace std; using namespace std;
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
Scope::Scope(ScopedSymbol *owner) Scope::Scope(ScopedSymbol *owner)
: _owner(owner), : _owner(owner),
@@ -312,4 +312,4 @@ Scope::iterator Scope::firstSymbol() const
Scope::iterator Scope::lastSymbol() const Scope::iterator Scope::lastSymbol() const
{ return _symbols + _symbolCount + 1; } { return _symbols + _symbolCount + 1; }
CPLUSPLUS_END_NAMESPACE

View File

@@ -51,8 +51,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Scope class CPLUSPLUS_EXPORT Scope
{ {
@@ -153,7 +153,7 @@ private:
int _hashSize; int _hashSize;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_SCOPE_H #endif // CPLUSPLUS_SCOPE_H

View File

@@ -59,7 +59,7 @@
#include "CheckExpression.h" #include "CheckExpression.h"
#include "CheckName.h" #include "CheckName.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
class Semantic::Data class Semantic::Data
{ {
@@ -252,4 +252,4 @@ int Semantic::visibilityForClassKey(int tokenKind) const
} }
} }
CPLUSPLUS_END_NAMESPACE

View File

@@ -52,8 +52,8 @@
#include "CPlusPlusForwardDeclarations.h" #include "CPlusPlusForwardDeclarations.h"
#include "ASTfwd.h" #include "ASTfwd.h"
CPLUSPLUS_BEGIN_HEADER
CPLUSPLUS_BEGIN_NAMESPACE namespace CPlusPlus {
class CPLUSPLUS_EXPORT Semantic class CPLUSPLUS_EXPORT Semantic
{ {
@@ -114,7 +114,7 @@ private:
Data *d; Data *d;
}; };
CPLUSPLUS_END_NAMESPACE } // end of namespace CPlusPlus
CPLUSPLUS_END_HEADER
#endif // CPLUSPLUS_SEMANTIC_H #endif // CPLUSPLUS_SEMANTIC_H

View File

@@ -49,7 +49,7 @@
#include "SemanticCheck.h" #include "SemanticCheck.h"
#include "Semantic.h" #include "Semantic.h"
CPLUSPLUS_BEGIN_NAMESPACE using namespace CPlusPlus;
SemanticCheck::SemanticCheck(Semantic *semantic) SemanticCheck::SemanticCheck(Semantic *semantic)
: ASTVisitor(semantic->control()), : ASTVisitor(semantic->control()),
@@ -65,4 +65,4 @@ Semantic *SemanticCheck::semantic() const
Control *SemanticCheck::control() const Control *SemanticCheck::control() const
{ return _semantic->control(); } { return _semantic->control(); }
CPLUSPLUS_END_NAMESPACE

Some files were not shown because too many files have changed in this diff Show More