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.putItem("valueeditable", "false");
d.putItem("numchild", n);
d.putItem("numchild", nn);
if (d.dumpChildren) {
QByteArray strippedInnerType = stripPointerType(d.innerType);
const char *stripped = innerIsPointerType ? strippedInnerType.data() : 0;
@@ -2998,10 +2998,26 @@ static void qDumpQWeakPointer(QDumper &d)
#endif // QT_VERSION >= 0x040500
#endif // QT_BOOTSTRAPPED
#ifdef Q_CC_MSVC
// A friendly list that grants access to its head.
template <class T> class FriendlyList : public std::list<T> {
public:
typedef _Node Node;
static const Node *head(const std::list<T> *list) {
return static_cast<const FriendlyList *>(list)->_Myhead;
}
};
#endif
static void qDumpStdList(QDumper &d)
{
const std::list<int> &list = *reinterpret_cast<const std::list<int> *>(d.data);
#ifdef Q_CC_MSVC
/* Extensive checks to avoid _HAS_ITERATOR_DEBUGGING asserts at all cost.
* Examine the head element which is present in empty lists as well.
* It could be even further checked if the type was known. */
const void *head = FriendlyList<int>::head(&list);
qCheckAccess(head);
const int size = static_cast<int>(list.size());
if (size < 0)
return;
@@ -3052,6 +3068,43 @@ static void qDumpStdList(QDumper &d)
d.disarm();
}
#ifdef Q_CC_MSVC
// A friendly red-black tree that is able to access the node type and head
// pointer. The class _Tree is used for the std::map/std::set implementations in
// MS VS CC. It has a head element pointer (with left and right) that exists
// even if it is empty. Provides a check() function to perform extensive checks
// to avoid _HAS_ITERATOR_DEBUGGING asserts at all cost.
template <class RedBlackTreeTraits> class FriendlyRedBlackTree : public std::_Tree<RedBlackTreeTraits> {
public:
static inline void check(const std::_Tree<RedBlackTreeTraits> *fs, bool *ok);
};
template <class RedBlackTreeTraits>
void FriendlyRedBlackTree<RedBlackTreeTraits>::check(const std::_Tree<RedBlackTreeTraits> *fs, bool *ok)
{
*ok = false;
const FriendlyRedBlackTree *friendlyTree = static_cast<const FriendlyRedBlackTree*>(fs);
// Check the red/black tree
const _Node *head = friendlyTree->_Myhead;
qCheckAccess(head);
if (head->_Color != _Red && head->_Color != _Black)
return;
const _Node *left = head->_Left;
if (left && left != head) {
qCheckAccess(left);
if (left->_Color != _Red && left->_Color != _Black)
return;
}
const _Node *right= head->_Right;
if (right && right != left) {
qCheckAccess(right);
if (right->_Color != _Red && right->_Color != _Black)
return;
}
*ok = true;
}
#endif
/* Dump out an arbitrary map. To iterate the map,
* it is cast to a map of <KeyType,Value>. 'int' can be used for both
* for all types if the implementation does not depend on the types
@@ -3072,6 +3125,16 @@ static void qDumpStdMapHelper(QDumper &d)
const int nn = map.size();
if (nn < 0)
return;
#ifdef Q_CC_MSVC
// Additional checks to avoid _HAS_ITERATOR_DEBUGGING asserts
typedef std::pair<const KeyType, ValueType> RedBlackTreeEntryType;
typedef std::_Tmap_traits<KeyType, ValueType, std::less<KeyType>, std::allocator<RedBlackTreeEntryType>, false>
MapRedBlackTreeTraits;
bool ok;
FriendlyRedBlackTree<MapRedBlackTreeTraits>::check(&map, &ok);
if (!ok)
return;
#endif
Q_TYPENAME DummyType::const_iterator it = map.begin();
const Q_TYPENAME DummyType::const_iterator cend = map.end();
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)
@@ -3178,6 +3241,15 @@ static void qDumpStdSetHelper(QDumper &d)
const int nn = set.size();
if (nn < 0)
return;
#ifdef Q_CC_MSVC
// Additional checks to avoid _HAS_ITERATOR_DEBUGGING asserts
typedef std::_Tset_traits<KeyType, std::less<KeyType> , std::allocator<KeyType>, false>
SetRedBlackTreeTraits;
bool ok;
FriendlyRedBlackTree<SetRedBlackTreeTraits>::check(&set, &ok);
if (!ok)
return;
#endif
Q_TYPENAME DummyType::const_iterator it = set.begin();
const Q_TYPENAME DummyType::const_iterator cend = set.end();
for (int i = 0; i < nn && i < 10 && it != cend; ++i, ++it)

View File

@@ -48,13 +48,32 @@
// Test uninitialized variables allocing memory
bool optTestUninitialized = false;
bool optTestAll = false;
bool optEmptyContainers = false;
unsigned optVerbose = 0;
// Provide address of type of be tested.
// When testing unitialized memory, allocate at random.
template <class T>
inline T* testAddress(T* in)
{
return optTestUninitialized ?
(reinterpret_cast<T*>(new char[sizeof(T)]))
: in;
unsigned char *mem = 0;
if (optTestUninitialized) {
mem = new unsigned char[sizeof(T)];
for (unsigned int i = 0; i < sizeof(T); i++) {
mem[i] = char(rand() % 255u);
}
} else {
mem = reinterpret_cast<unsigned char*>(in);
}
if (optVerbose) {
for (unsigned int i = 0; i < sizeof(T); i++) {
unsigned int b = mem[i];
printf("%2d %2x %3d\n", i, b, b);
}
fflush(stdout);
}
return reinterpret_cast<T*>(mem);
}
/* Test program for Dumper development/porting.
@@ -175,8 +194,10 @@ static int dumpQMapIntInt()
QMap<int,int> test;
QMapNode<int,int> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(42, 43);
test.insert(43, 44);
if (!optEmptyContainers) {
test.insert(42, 43);
test.insert(43, 44);
}
prepareInBuffer("QMap", "local.qmapintint", "local.qmapintint", "int@int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(int), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout);
@@ -189,8 +210,10 @@ static int dumpQMapIntString()
QMap<int,QString> test;
QMapNode<int,QString> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(42, QLatin1String("fortytwo"));
test.insert(43, QLatin1String("fortytree"));
if (!optEmptyContainers) {
test.insert(42, QLatin1String("fortytwo"));
test.insert(43, QLatin1String("fortytree"));
}
prepareInBuffer("QMap", "local.qmapintqstring", "local.qmapintqstring", "int@QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(QString), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout);
@@ -201,8 +224,10 @@ static int dumpQMapIntString()
static int dumpQSetInt()
{
QSet<int> test;
test.insert(42);
test.insert(43);
if (!optEmptyContainers) {
test.insert(42);
test.insert(43);
}
prepareInBuffer("QSet", "local.qsetint", "local.qsetint", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), 0, 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -216,9 +241,11 @@ static int dumpQMapQStringString()
QMap<QString,QString> test;
QMapNode<QString,QString> mapNode;
const int valueOffset = (char*)&(mapNode.value) - (char*)&mapNode;
test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
test.insert(QLatin1String("423"), QLatin1String("fortytree"));
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString");
if (!optEmptyContainers) {
test.insert(QLatin1String("42s"), QLatin1String("fortytwo"));
test.insert(QLatin1String("423"), QLatin1String("fortytree"));
}
prepareInBuffer("QMap", "local.qmapqstringqstring", "local.qmapqstringqstring", "QString@QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(QString), sizeof(mapNode), valueOffset);
fputs(qDumpOutBuffer, stdout);
fputc('\n', stdout);
@@ -278,8 +305,10 @@ static int dumpStdWString()
static int dumpStdStringList()
{
std::list<std::string> test;
test.push_back("item1");
test.push_back("item2");
if (!optEmptyContainers) {
test.push_back("item1");
test.push_back("item2");
}
prepareInBuffer("std::list", "local.stringlist", "local.stringlist", "std::string");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<std::string>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -290,8 +319,10 @@ static int dumpStdStringList()
static int dumpStdStringQList()
{
QList<std::string> test;
test.push_back("item1");
test.push_back("item2");
if (!optEmptyContainers) {
test.push_back("item1");
test.push_back("item2");
}
prepareInBuffer("QList", "local.stringqlist", "local.stringqlist", "std::string");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), 0, 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -302,8 +333,10 @@ static int dumpStdStringQList()
static int dumpStdIntList()
{
std::list<int> test;
test.push_back(1);
test.push_back(2);
if (!optEmptyContainers) {
test.push_back(1);
test.push_back(2);
}
prepareInBuffer("std::list", "local.intlist", "local.intlist", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -314,8 +347,10 @@ static int dumpStdIntList()
static int dumpStdIntVector()
{
std::vector<int> test;
test.push_back(1);
test.push_back(2);
if (!optEmptyContainers) {
test.push_back(1);
test.push_back(2);
}
prepareInBuffer("std::vector", "local.intvector", "local.intvector", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -326,8 +361,10 @@ static int dumpStdIntVector()
static int dumpStdStringVector()
{
std::vector<std::string> test;
test.push_back("item1");
test.push_back("item2");
if (!optEmptyContainers) {
test.push_back("item1");
test.push_back("item2");
}
prepareInBuffer("std::vector", "local.stringvector", "local.stringvector", "std::string");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -338,8 +375,10 @@ static int dumpStdStringVector()
static int dumpStdWStringVector()
{
std::vector<std::wstring> test;
test.push_back(L"item1");
test.push_back(L"item2");
if (!optEmptyContainers) {
test.push_back(L"item1");
test.push_back(L"item2");
}
prepareInBuffer("std::vector", "local.wstringvector", "local.wstringvector", "std::wstring");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::wstring), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -350,8 +389,10 @@ static int dumpStdWStringVector()
static int dumpStdIntSet()
{
std::set<int> test;
test.insert(1);
test.insert(2);
if (!optEmptyContainers) {
test.insert(1);
test.insert(2);
}
prepareInBuffer("std::set", "local.intset", "local.intset", "int");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(int), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -362,8 +403,10 @@ static int dumpStdIntSet()
static int dumpStdStringSet()
{
std::set<std::string> test;
test.insert("item1");
test.insert("item2");
if (!optEmptyContainers) {
test.insert("item1");
test.insert("item2");
}
prepareInBuffer("std::set", "local.stringset", "local.stringset", "std::string");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -374,8 +417,10 @@ static int dumpStdStringSet()
static int dumpStdQStringSet()
{
std::set<QString> test;
test.insert(QLatin1String("item1"));
test.insert(QLatin1String("item2"));
if (!optEmptyContainers) {
test.insert(QLatin1String("item1"));
test.insert(QLatin1String("item2"));
}
prepareInBuffer("std::set", "local.stringset", "local.stringset", "QString");
qDumpObjectData440(2, 42, testAddress(&test), 1, sizeof(QString), sizeof(std::list<int>::allocator_type), 0, 0);
fputs(qDumpOutBuffer, stdout);
@@ -385,9 +430,11 @@ static int dumpStdQStringSet()
static int dumpStdMapIntString()
{
std::map<int,std::string> test;
std::map<int,std::string> test;
std::map<int,std::string>::value_type entry(42, std::string("fortytwo"));
test.insert(entry);
if (!optEmptyContainers) {
test.insert(entry);
}
const int valueOffset = (char*)&(entry.second) - (char*)&entry;
prepareInBuffer("std::map", "local.stdmapintstring", "local.stdmapintstring",
"int@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const int,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >");
@@ -402,7 +449,9 @@ static int dumpStdMapStringString()
typedef std::map<std::string,std::string> TestType;
TestType test;
const TestType::value_type entry("K", "V");
test.insert(entry);
if (!optEmptyContainers) {
test.insert(entry);
}
const int valueOffset = (char*)&(entry.second) - (char*)&entry;
prepareInBuffer("std::map", "local.stdmapstringstring", "local.stdmapstringstring",
"std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::basic_string<char,std::char_traits<char>,std::allocator<char> >@std::less<int>@std::allocator<std::pair<const std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >");
@@ -502,6 +551,23 @@ static TypeDumpFunctionMap registerTypes()
return rc;
}
static void usage(const char *b, const TypeDumpFunctionMap &tdm)
{
printf("Usage: %s [-v][-u][-e] <type1> <type2..>\n", b);
printf("Usage: %s [-v][-u][-e] -a excluded_type1 <excluded_type2...>\n", b);
printf("Options: -u Test uninitialized memory\n");
printf(" -e Empty containers\n");
printf(" -v Verbose\n");
printf(" -a Test all available types\n");
printf("Supported types: ");
const TypeDumpFunctionMap::const_iterator cend = tdm.constEnd();
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
fputs(qPrintable(it.key()), stdout);
fputc(' ', stdout);
}
fputc('\n', stdout);
}
int main(int argc, char *argv[])
{
printf("\nQt Creator Debugging Helper testing tool\n\n");
@@ -515,30 +581,57 @@ int main(int argc, char *argv[])
const TypeDumpFunctionMap::const_iterator cend = tdm.constEnd();
if (argc < 2) {
printf("Usage: %s [-a]|<type1> <type2..>\n", argv[0]);
printf("Supported types: ");
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
fputs(qPrintable(it.key()), stdout);
fputc(' ', stdout);
}
fputc('\n', stdout);
usage(argv[0], tdm);
return 0;
}
// Parse args
QStringList tests;
for (int a = 1; a < argc; a++) {
const char *arg = argv[a];
if (arg[0] == '-') {
switch (arg[1]) {
case 'a':
optTestAll = true;
break;
case 'u':
optTestUninitialized = true;
break;
case 'v':
optVerbose++;
break;
case 'e':
optEmptyContainers = true;
break;
default:
fprintf(stderr, "Invalid option %s\n", arg);
usage(argv[0], tdm);
return -1;
}
} else {
tests.push_back(QLatin1String(arg));
}
}
// Go
int rc = 0;
if (argc == 2 && !qstrcmp(argv[1], "-a")) {
if (optTestAll) {
for (TypeDumpFunctionMap::const_iterator it = tdm.constBegin(); it != cend; ++it) {
printf("\nTesting: %s\n", qPrintable(it.key()));
rc += (*it.value())();
const QString test = it.key();
if (tests.contains(test)) {
printf("\nSkipping: %s\n", qPrintable(test));
} else {
printf("\nTesting: %s\n", qPrintable(test));
rc += (*it.value())();
if (optTestUninitialized)
printf("Survived: %s\n", qPrintable(test));
}
}
} else {
for (int i = 1; i < argc; i++) {
const char *arg = argv[i];
printf("\nTesting: %s\n", arg);
const TypeDumpFunctionMap::const_iterator it = tdm.constFind(QLatin1String(arg));
foreach(const QString &test, tests) {
printf("\nTesting: %s\n", qPrintable(test));
const TypeDumpFunctionMap::const_iterator it = tdm.constFind(test);
if (it == cend) {
rc = -1;
fprintf(stderr, "\nUnhandled type: %s\n", argv[i]);
fprintf(stderr, "\nUnhandled type: %s\n", qPrintable(test));
} else {
rc = (*it.value())();
}

View File

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

View File

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

View File

@@ -341,6 +341,8 @@ void CdbDumperInitThread ::run()
CdbDumperHelper::CdbDumperHelper(DebuggerManager *manager,
CdbComInterfaces *cif) :
m_tryInjectLoad(true),
m_msgDisabled(QLatin1String("Dumpers are disabled")),
m_msgNotInScope(QLatin1String("Data not in scope")),
m_state(NotLoaded),
m_manager(manager),
m_cif(cif),
@@ -561,8 +563,14 @@ CdbDumperHelper::CallResult
if (!writeToDebuggee(m_cif->debugDataSpaces, inBuffer, m_inBufferAddress, errorMessage))
return CallFailed;
}
if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, callCmd, errorMessage))
if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, callCmd, errorMessage)) {
// Clear the outstanding call in case we triggered a debug library assert with a message box
QString clearError;
if (!CdbDebugEnginePrivate::executeDebuggerCommand(m_cif->debugControl, QLatin1String(".call /c"), &clearError)) {
*errorMessage += QString::fromLatin1("/Unable to clear call %1").arg(clearError);
}
return CallSyntaxError;
}
// Set up call and a temporary breakpoint after it.
// Try to skip debuggee crash exceptions and dumper exceptions
// by using 'gN' (go not handled -> pass handling to dumper __try/__catch block)
@@ -648,8 +656,12 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpTypeI(const WatchData &wd, bool
{
errorMessage->clear();
// Check failure cache and supported types
if (m_state == Disabled) {
*errorMessage = QLatin1String("Dumpers are disabled");
if (m_state == Disabled) {
*errorMessage =m_msgDisabled;
return DumpNotHandled;
}
if (wd.error) {
*errorMessage =m_msgNotInScope;
return DumpNotHandled;
}
if (m_failedTypes.contains(wd.type)) {

View File

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

View File

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

View File

@@ -33,8 +33,11 @@
#include "cdbsymbolgroupcontext.h"
#include "cdbdebugengine_p.h"
#include "cdbdumperhelper.h"
#include "debuggeractions.h"
#include "debuggermanager.h"
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
namespace Debugger {
@@ -85,6 +88,7 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
if (debugCDB)
qDebug() << Q_FUNC_INFO << frameCount;
const QChar exclamationMark = QLatin1Char('!');
m_frameContexts.resize(frameCount);
qFill(m_frameContexts, static_cast<CdbStackFrameContext*>(0));
@@ -99,7 +103,11 @@ bool CdbStackTraceContext::init(unsigned long frameCount, QString * /*errorMessa
frame.address = QString::fromLatin1("0x%1").arg(instructionOffset, 0, 16);
m_cif->debugSymbols->GetNameByOffsetWide(instructionOffset, wszBuf, MAX_PATH, 0, 0);
// Determine function and module, if available
frame.function = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf));
const int moduleSepPos = frame.function.indexOf(exclamationMark);
if (moduleSepPos != -1)
frame.from = frame.function.mid(0, moduleSepPos);
ULONG ulLine;
ULONG64 ul64Displacement;
@@ -160,7 +168,13 @@ CdbStackFrameContext *CdbStackTraceContext::frameContextAt(int index, QString *e
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
return 0;
}
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, errorMessage);
// Exclude unitialized variables if desired
QStringList uninitializedVariables;
if (theDebuggerAction(UseCodeModel)->isChecked()) {
const StackFrame &frame = m_frames.at(index);
getUninitializedVariables(DebuggerManager::instance()->cppCodeModelSnapshot(), frame.function, frame.file, frame.line, &uninitializedVariables);
}
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(QLatin1String("local"), sg, uninitializedVariables, errorMessage);
if (!sc) {
*errorMessage = msgFrameContextFailed(index, m_frames.at(index), *errorMessage);
return 0;

View File

@@ -39,6 +39,9 @@
enum { debug = 0 };
enum { debugInternalDumpers = 0 };
// name separator for shadowed variables
static const char iNameShadowDelimiter = '#';
static inline QString msgSymbolNotFound(const QString &s)
{
return QString::fromLatin1("The symbol '%1' could not be found.").arg(s);
@@ -83,6 +86,14 @@ QTextStream &operator<<(QTextStream &str, const DEBUG_SYMBOL_PARAMETERS &p)
return str;
}
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
{
ULONG64 rc = 0;
if (FAILED(sg->GetSymbolOffset(index, &rc)))
rc = 0;
return QLatin1String("0x") + QString::number(rc, 16);
}
// A helper function to extract a string value from a member function of
// IDebugSymbolGroup2 taking the symbol index and a character buffer.
// Pass in the the member function as '&IDebugSymbolGroup2::GetSymbolNameWide'
@@ -129,12 +140,15 @@ static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMB
}
CdbSymbolGroupContext::CdbSymbolGroupContext(const QString &prefix,
CIDebugSymbolGroup *symbolGroup) :
CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables) :
m_prefix(prefix),
m_nameDelimiter(QLatin1Char('.')),
m_uninitializedVariables(uninitializedVariables.toSet()),
m_symbolGroup(symbolGroup),
m_unnamedSymbolNumber(1)
{
}
CdbSymbolGroupContext::~CdbSymbolGroupContext()
@@ -144,9 +158,10 @@ CdbSymbolGroupContext::~CdbSymbolGroupContext()
CdbSymbolGroupContext *CdbSymbolGroupContext::create(const QString &prefix,
CIDebugSymbolGroup *symbolGroup,
const QStringList &uninitializedVariables,
QString *errorMessage)
{
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup);
CdbSymbolGroupContext *rc = new CdbSymbolGroupContext(prefix, symbolGroup, uninitializedVariables);
if (!rc->init(errorMessage)) {
delete rc;
return 0;
@@ -173,28 +188,36 @@ bool CdbSymbolGroupContext::init(QString *errorMessage)
*errorMessage = QString::fromLatin1("In %1: %2 (%3 symbols)").arg(QLatin1String(Q_FUNC_INFO), msgComFailed("GetSymbolParameters", hr)).arg(count);
return false;
}
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, 0, count);
populateINameIndexMap(m_prefix, DEBUG_ANY_ID, count);
}
if (debug)
qDebug() << Q_FUNC_INFO << '\n'<< toString();
qDebug() << Q_FUNC_INFO << '\n'<< toString(true);
return true;
}
/* Make the entries for iname->index mapping. We might encounter
* already expanded subitems when doing it for top-level ('this'-pointers),
* recurse in that case, (skip over expanded children).
* Loop backwards to detect shadowed variables in the order the
/* debugger expects them:
\code
int x; // Occurrence (1), should be reported as "x <shadowed 1>"
if (true) {
int x = 5; (2) // Occurrence (2), should be reported as "x"
}
\endcode
* The order in the symbol group is (1),(2). Give them an iname of
* <root>#<shadowed-nr>, which will be split apart for display. */
void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigned long parentId,
unsigned long start, unsigned long count)
unsigned long end)
{
// Make the entries for iname->index mapping. We might encounter
// already expanded subitems when doing it for top-level, recurse in that case.
const QString symbolPrefix = prefix + m_nameDelimiter;
if (debug)
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << start << count;
const unsigned long end = m_symbolParameters.size();
unsigned long seenChildren = 0;
// Skip over expanded children
for (unsigned long i = start; i < end && seenChildren < count; i++) {
qDebug() << Q_FUNC_INFO << '\n'<< symbolPrefix << parentId << end;
for (unsigned long i = end - 1; ; i--) {
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(i);
if (parentId == p.ParentSymbol) {
seenChildren++;
// "__formal" occurs when someone writes "void foo(int /* x */)..."
static const QString unnamedFormalParameter = QLatin1String("__formal");
QString symbolName = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
@@ -203,11 +226,21 @@ void CdbSymbolGroupContext::populateINameIndexMap(const QString &prefix, unsigne
symbolName += QString::number(m_unnamedSymbolNumber++);
symbolName += QLatin1Char('>');
}
const QString name = symbolPrefix + symbolName;
// Find a unique name in case the variable is shadowed by
// an existing one
const QString namePrefix = symbolPrefix + symbolName;
QString name = namePrefix;
for (int n = 1; m_inameIndexMap.contains(name); n++) {
name.truncate(namePrefix.size());
name += QLatin1Char(iNameShadowDelimiter);
name += QString::number(n);
}
m_inameIndexMap.insert(name, i);
if (getSymbolState(p) == ExpandedSymbol)
populateINameIndexMap(name, i, i + 1, p.SubElements);
populateINameIndexMap(name, i, i + 1 + p.SubElements);
}
if (i == 0 || i == parentId)
break;
}
}
@@ -223,7 +256,10 @@ QString CdbSymbolGroupContext::toString(bool verbose) const
str << " ";
str << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolNameWide, i);
if (p.Flags & DEBUG_SYMBOL_IS_LOCAL)
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i);
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, i) << '\'';
str << " Address: " << hexSymbolOffset(m_symbolGroup, i);
if (verbose)
str << " '" << getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, i) << '\'';
str << p << '\n';
}
if (verbose) {
@@ -348,7 +384,7 @@ bool CdbSymbolGroupContext::expandSymbol(const QString &prefix, unsigned long in
if (it.value() > index)
it.value() += newSymbolCount;
// insert the new symbols
populateINameIndexMap(prefix, index, index + 1, newSymbolCount);
populateINameIndexMap(prefix, index, index + 1 + newSymbolCount);
if (debug > 1)
qDebug() << '<' << Q_FUNC_INFO << '\n' << prefix << index << '\n' << toString();
return true;
@@ -365,14 +401,6 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
return m_inameIndexMap.key(index);
}
static inline QString hexSymbolOffset(CIDebugSymbolGroup *sg, unsigned long index)
{
ULONG64 rc = 0;
if (FAILED(sg->GetSymbolOffset(index, &rc)))
rc = 0;
return QLatin1String("0x") + QString::number(rc, 16);
}
// check for "0x000", "0x000 class X"
static inline bool isNullPointer(const WatchData &wd)
{
@@ -409,19 +437,35 @@ static inline QString fixValue(const QString &value)
return removeInnerTemplateType(value);
}
WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
{
WatchData wd;
wd.iname = symbolINameAt(index);
wd.exp = wd.iname;
// Determine name from iname and format shadowed variables correctly
// as "<shadowed X>, see populateINameIndexMap().
const int lastDelimiterPos = wd.iname.lastIndexOf(m_nameDelimiter);
QString name = lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1);
int shadowedNumber = 0;
const int shadowedPos = name.lastIndexOf(QLatin1Char(iNameShadowDelimiter));
if (shadowedPos != -1) {
shadowedNumber = name.mid(shadowedPos + 1).toInt();
name.truncate(shadowedPos);
}
// For class hierarchies, we get sometimes complicated std::template types here.
// Remove them for display
wd.name = removeInnerTemplateType(lastDelimiterPos == -1 ? wd.iname : wd.iname.mid(lastDelimiterPos + 1));
// (std::map extends std::tree<>... Remove them for display only.
const QString fullShadowedName = WatchData::shadowedName(name, shadowedNumber);
wd.name = WatchData::shadowedName(removeInnerTemplateType(name), shadowedNumber);
wd.addr = hexSymbolOffset(m_symbolGroup, index);
const QString type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index);
const QString type = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolTypeNameWide, index);
wd.setType(type);
// Check for unitialized variables at level 0 only.
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(index);
if (p.ParentSymbol == DEBUG_ANY_ID && m_uninitializedVariables.contains(fullShadowedName)) {
wd.setError(WatchData::msgNotInScope());
return wd;
}
const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
wd.setType(type);
wd.setValue(fixValue(value));
wd.setChildrenNeeded(); // compensate side effects of above setters
// Figure out children. The SubElement is only a guess unless the symbol,
@@ -429,7 +473,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
// If the symbol has children (expanded or not), we leave the 'Children' flag
// in 'needed' state. Suppress 0-pointers right ("0x000 class X")
// here as they only lead to children with memory access errors.
const bool hasChildren = m_symbolParameters.at(index).SubElements && !isNullPointer(wd);
const bool hasChildren = p.SubElements && !isNullPointer(wd);
wd.setHasChildren(hasChildren);
if (debug > 1)
qDebug() << Q_FUNC_INFO << index << '\n' << wd.toString();
@@ -438,7 +482,7 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
WatchData CdbSymbolGroupContext::dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index)
{
WatchData rc = symbolAt(index);
WatchData rc = watchDataAt(index);
dump(ds, &rc);
return rc;
}

View File

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

View File

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

View File

@@ -229,6 +229,13 @@ DebuggerSettings *DebuggerSettings::instance()
item->setValue(false);
instance->insertItem(DebugDebuggingHelpers, item);
item = new SavedAction(instance);
item->setSettingsKey(debugModeGroup, QLatin1String("UseCodeModel"));
item->setText(tr("Use code model"));
item->setCheckable(true);
item->setDefaultValue(false);
item->setValue(false);
instance->insertItem(UseCodeModel, item);
item = new SavedAction(instance);
item->setText(tr("Recheck debugging helper availability"));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<width>432</width>
<height>434</height>
</rect>
</property>
@@ -83,10 +83,20 @@
</widget>
</item>
<item>
<widget class="Utils::PathChooser" name="dumperLocationChooser" native="true"/>
<widget class="Utils::PathChooser" name="dumperLocationChooser"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBoxUseCodeModel">
<property name="toolTip">
<string>Makes use of Qt Creator's code model to find out if a variable has already been assigned a value at the point the debugger interrupts.</string>
</property>
<property name="text">
<string>Use code model</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxDebugDebuggingHelpers">
<property name="toolTip">

View File

@@ -31,7 +31,6 @@
#include <utils/qtcassert.h>
#include <QtCore/QObject>
#include <QtCore/QProcess>
namespace Debugger {
@@ -47,35 +46,22 @@ AbstractGdbAdapter::~AbstractGdbAdapter()
disconnect();
}
// This cannot be in the c'tor, as it would not connect the "virtual" slots
void AbstractGdbAdapter::commonInit()
void AbstractGdbAdapter::shutdown()
{
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(handleGdbError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(started()),
this, SLOT(handleGdbStarted()));
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
this, SIGNAL(readyReadStandardError()));
}
QByteArray AbstractGdbAdapter::readAllStandardOutput()
void AbstractGdbAdapter::startInferiorPhase2()
{
return m_gdbProc.readAllStandardOutput();
}
QByteArray AbstractGdbAdapter::readAllStandardError()
const char *AbstractGdbAdapter::inferiorShutdownCommand() const
{
return m_gdbProc.readAllStandardError();
return "kill";
}
void AbstractGdbAdapter::write(const QByteArray &data)
{
m_gdbProc.write(data);
m_engine->m_gdbProc.write(data);
}
bool AbstractGdbAdapter::isTrkAdapter() const

View File

@@ -42,7 +42,7 @@ namespace Internal {
// debugging and TrkGdbAdapter used for on-device debugging.
// In the PlainGdbAdapter case it's just a wrapper around a QProcess running
// gdb, in the TrkGdbAdapter case it's the interface to the gdb process in
// the whole rfomm/gdb/gdbserver combo.
// the whole rfcomm/gdb/gdbserver combo.
class AbstractGdbAdapter : public QObject
{
Q_OBJECT
@@ -51,34 +51,44 @@ public:
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0);
virtual ~AbstractGdbAdapter();
QByteArray readAllStandardOutput();
QByteArray readAllStandardError();
virtual void write(const QByteArray &data);
virtual bool isTrkAdapter() const; // isUtterlyBrokenAdapter
virtual void startAdapter() = 0;
virtual void startInferior() = 0;
virtual void startInferiorPhase2();
virtual void interruptInferior() = 0;
virtual void shutdown() = 0;
virtual void shutdown();
virtual const char *inferiorShutdownCommand() const;
virtual bool dumpersAvailable() const = 0;
static QString msgGdbStopFailed(const QString &why);
static QString msgInferiorStopFailed(const QString &why);
static QString msgAttachedToStoppedInferior();
static QString msgInferiorStarted();
static QString msgInferiorRunning();
static QString msgConnectRemoteServerFailed(const QString &why);
signals:
void adapterStarted();
// Something went wrong with the adapter *before* adapterStarted() was emitted.
// Make sure to clean up everything before emitting this signal.
void adapterStartFailed(const QString &msg, const QString &settingsIdHint);
void adapterShutDown();
void adapterShutdownFailed(const QString &msg);
// Something went wrong with the adapter *after* adapterStarted() was emitted.
// Make sure to clean up everything before emitting this signal.
void adapterCrashed(const QString &msg);
void inferiorStartFailed(const QString &msg);
void inferiorShutDown();
void inferiorShutdownFailed(const QString &msg);
void readyReadStandardOutput();
void readyReadStandardError();
// This triggers the initial breakpoint synchronization and causes
// startInferiorPhase2() being called once done.
void inferiorPrepared();
// The adapter is still running just fine, but it failed to acquire a debuggee.
void inferiorStartFailed(const QString &msg);
protected:
void commonInit();
DebuggerState state() const
{ return m_engine->state(); }
void setState(DebuggerState state)
@@ -89,17 +99,10 @@ protected:
{ m_engine->debugMessage(msg); }
void showStatusMessage(const QString &msg) const
{ m_engine->showStatusMessage(msg); }
static QString msgGdbStopFailed(const QString &why);
static QString msgInferiorStopFailed(const QString &why);
static QString msgAttachedToStoppedInferior();
static QString msgInferiorStarted();
static QString msgInferiorRunning();
static QString msgConnectRemoteServerFailed(const QString &why);
void showMessageBox(int icon, const QString &title, const QString &text) const
{ m_engine->showMessageBox(icon, title, text); }
GdbEngine * const m_engine;
QProcess m_gdbProc;
};
} // namespace Internal

View File

@@ -29,7 +29,6 @@
#include "attachgdbadapter.h"
#include "debuggeractions.h"
#include "gdbengine.h"
#include "procinterrupt.h"
#include "debuggerstringutils.h"
@@ -53,7 +52,6 @@ namespace Internal {
AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent)
{
commonInit();
}
void AttachGdbAdapter::startAdapter()
@@ -62,28 +60,12 @@ void AttachGdbAdapter::startAdapter()
setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs;
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
if (!m_engine->startGdb())
return;
QString location = theDebuggerStringSetting(GdbLocation);
m_gdbProc.start(location, gdbArgs);
}
void AttachGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit adapterStarted();
}
void AttachGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
shutdown();
}
void AttachGdbAdapter::startInferior()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
@@ -99,6 +81,7 @@ void AttachGdbAdapter::handleAttach(const GdbResponse &response)
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
debugMessage(_("INFERIOR ATTACHED"));
showStatusMessage(msgAttachedToStoppedInferior());
emit inferiorPrepared();
m_engine->updateAll();
} else {
QString msg = __(response.data.findChild("msg").data());
@@ -114,59 +97,5 @@ void AttachGdbAdapter::interruptInferior()
debugMessage(_("CANNOT INTERRUPT %1").arg(pid));
}
void AttachGdbAdapter::shutdown()
{
switch (state()) {
case InferiorStartFailed:
m_engine->postCommand(_("-gdb-exit"));
setState(DebuggerNotReady);
return;
case InferiorStopped:
setState(InferiorShuttingDown);
m_engine->postCommand(_("detach"), CB(handleDetach));
return;
case InferiorShutDown:
setState(AdapterShuttingDown);
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
return;
default:
QTC_ASSERT(false, qDebug() << state());
}
}
void AttachGdbAdapter::handleDetach(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
setState(InferiorShutDown);
emit inferiorShutDown();
shutdown(); // re-iterate...
} else {
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
setState(InferiorShutdownFailed);
emit inferiorShutdownFailed(msg);
}
}
void AttachGdbAdapter::handleExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
// don't set state here, this will be handled in handleGdbFinished()
} else {
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
emit adapterShutdownFailed(msg);
}
}
void AttachGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
{
debugMessage(_("GDB PROESS FINISHED"));
setState(DebuggerNotReady);
emit adapterShutDown();
}
} // namespace Internal
} // namespace Debugger

View File

@@ -31,10 +31,6 @@
#define DEBUGGER_ATTACHGDBADAPTER_H
#include "abstractgdbadapter.h"
#include "gdbengine.h"
#include <QtCore/QDebug>
#include <QtCore/QProcess>
namespace Debugger {
namespace Internal {
@@ -57,16 +53,10 @@ public:
void startAdapter();
void startInferior();
void interruptInferior();
void shutdown();
const char *inferiorShutdownCommand() const { return "detach"; }
private:
void handleAttach(const GdbResponse &response);
void handleDetach(const GdbResponse &response);
void handleExit(const GdbResponse &response);
Q_SLOT void handleGdbStarted();
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbError(QProcess::ProcessError error);
};
} // namespace Internal

View File

@@ -35,7 +35,9 @@
#include <utils/qtcassert.h>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtGui/QMessageBox>
namespace Debugger {
namespace Internal {
@@ -53,7 +55,6 @@ namespace Internal {
CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent)
{
commonInit();
}
void CoreGdbAdapter::startAdapter()
@@ -62,85 +63,42 @@ void CoreGdbAdapter::startAdapter()
setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs;
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
if (!m_engine->startGdb())
return;
QString location = theDebuggerStringSetting(GdbLocation);
m_gdbProc.start(location, gdbArgs);
}
void CoreGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit adapterStarted();
}
void CoreGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
shutdown();
}
void CoreGdbAdapter::startInferior()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QFileInfo fi(startParameters().coreFile);
m_executable = startParameters().executable;
if (m_executable.isEmpty()) {
#ifdef EXE_FROM_CORE
// Extra round trip to get executable name from core file.
// This is sometimes not the full name, so it can't be used
// as the generic solution.
// Quoting core name below fails in gdb 6.8-debian.
QString coreName = fi.absoluteFilePath();
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore1));
} else {
// Directly load symbols.
QFileInfo fi(m_executable);
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
m_round = 1;
loadCoreFile();
#else
showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"),
tr("No executable to load symbols from specified."));
#endif
return;
}
#ifdef EXE_FROM_CORE
m_round = 2;
#endif
loadExeAndSyms();
}
void CoreGdbAdapter::handleTargetCore1(const GdbResponse &response)
void CoreGdbAdapter::loadExeAndSyms()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) {
showStatusMessage(tr("Attached to core temporarily."));
GdbMi console = response.data.findChild("consolestreamoutput");
int pos1 = console.data().indexOf('`');
int pos2 = console.data().indexOf('\'');
if (pos1 == -1 || pos2 == -1) {
emit inferiorStartFailed(tr("No binary found."));
} else {
m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1);
// Strip off command line arguments. FIXME: make robust.
if (m_executable.contains(' '))
m_executable = m_executable.section(' ', 0, 0);
QTC_ASSERT(!m_executable.isEmpty(), /**/);
// Finish extra round.
m_engine->postCommand(_("detach"), CB(handleDetach1));
}
} else {
const QByteArray msg = response.data.findChild("msg").data();
emit inferiorStartFailed(msg);
}
}
void CoreGdbAdapter::handleDetach1(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) {
// Load symbols.
QFileInfo fi(m_executable);
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
} else {
const QByteArray msg = response.data.findChild("msg").data();
emit inferiorStartFailed(msg);
}
// Do that first, otherwise no symbols are loaded.
QFileInfo fi(m_executable);
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
.arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
}
void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
@@ -148,74 +106,70 @@ void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) {
showStatusMessage(tr("Symbols found."));
// Quoting core name below fails in gdb 6.8-debian.
QFileInfo fi(startParameters().coreFile);
QString coreName = fi.absoluteFilePath();
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore2));
} else {
QString msg = tr("Symbols not found in \"%1\" failed:\n%2")
.arg(__(response.data.findChild("msg").data()));
setState(InferiorUnrunnable);
m_engine->updateAll();
// emit inferiorStartFailed(msg);
QString msg = tr("Loading symbols from \"%1\" failed:\n").arg(m_executable)
+ __(response.data.findChild("msg").data());
showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), msg);
}
loadCoreFile();
}
void CoreGdbAdapter::handleTargetCore2(const GdbResponse &response)
void CoreGdbAdapter::loadCoreFile()
{
// Quoting core name below fails in gdb 6.8-debian.
QFileInfo fi(startParameters().coreFile);
QString coreName = fi.absoluteFilePath();
m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore));
}
void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) {
#ifdef EXE_FROM_CORE
if (m_round == 1) {
m_round = 2;
GdbMi console = response.data.findChild("consolestreamoutput");
int pos1 = console.data().indexOf('`');
int pos2 = console.data().indexOf('\'');
if (pos1 != -1 && pos2 != -1) {
m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1);
// Strip off command line arguments. FIXME: make robust.
int idx = m_executable.indexOf(_c(' '));
if (idx >= 0)
m_executable.truncate(idx);
if (!m_executable.isEmpty()) {
m_executable = QFileInfo(startParameters().coreFile).absoluteDir()
.absoluteFilePath(m_executable);
if (QFile::exists(m_executable)) {
// Finish extra round ...
showStatusMessage(tr("Attached to core temporarily."));
m_engine->postCommand(_("detach"));
// ... and retry.
loadExeAndSyms();
return;
}
}
}
showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"),
tr("Unable to determine executable from core file."));
}
#endif
showStatusMessage(tr("Attached to core."));
setState(InferiorUnrunnable);
m_engine->updateAll();
} else {
QString msg = tr("Attach to core \"%1\" failed:\n%2")
.arg(__(response.data.findChild("msg").data()));
setState(InferiorUnrunnable);
m_engine->updateAll();
// emit inferiorStartFailed(msg);
QString msg = tr("Attach to core \"%1\" failed:\n").arg(startParameters().coreFile)
+ __(response.data.findChild("msg").data());
emit inferiorStartFailed(msg);
}
}
void CoreGdbAdapter::interruptInferior()
{
// A core should never 'run'
QTC_ASSERT(false, /**/);
}
void CoreGdbAdapter::shutdown()
{
switch (state()) {
case DebuggerNotReady:
return;
case InferiorUnrunnable:
case InferiorShutDown:
setState(AdapterShuttingDown);
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
return;
default:
QTC_ASSERT(false, qDebug() << state());
}
}
void CoreGdbAdapter::handleExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
// don't set state here, this will be handled in handleGdbFinished()
} else {
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
emit adapterShutdownFailed(msg);
}
}
void CoreGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
{
debugMessage(_("GDB PROESS FINISHED"));
setState(DebuggerNotReady);
emit adapterShutDown();
}
} // namespace Internal
} // namespace Debugger

View File

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

View File

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

View File

@@ -37,6 +37,7 @@
#include "attachgdbadapter.h"
#include "coregdbadapter.h"
#include "plaingdbadapter.h"
#include "termgdbadapter.h"
#include "remotegdbadapter.h"
#include "trkgdbadapter.h"
@@ -89,10 +90,6 @@
#endif
#include <ctype.h>
// FIXME: temporary hack to evalaute tbreak based step-over behaviour
static QString lastFile;
static int lastLine;
namespace Debugger {
namespace Internal {
@@ -109,17 +106,29 @@ namespace Internal {
static bool stateAcceptsGdbCommands(DebuggerState state)
{
return state == AdapterStarted
|| state == InferiorUnrunnable
|| state == InferiorStarting
|| state == InferiorRunningRequested
|| state == InferiorRunning
|| state == InferiorStopping
|| state == InferiorStopped
|| state == InferiorShuttingDown
|| state == InferiorShutDown
|| state == AdapterShuttingDown;
};
switch (state) {
case AdapterStarting:
case AdapterStarted:
case AdapterStartFailed:
case InferiorUnrunnable:
case InferiorStarting:
case InferiorStartFailed:
case InferiorRunningRequested:
case InferiorRunning:
case InferiorStopping:
case InferiorStopped:
case InferiorShuttingDown:
case InferiorShutDown:
case InferiorShutdownFailed:
return true;
case DebuggerNotReady:
case EngineStarting:
case InferiorStopFailed:
case EngineShuttingDown:
break;
}
return false;
}
static int &currentToken()
{
@@ -221,27 +230,16 @@ GdbEngine::~GdbEngine()
void GdbEngine::connectAdapter()
{
// Gdb Process interaction
connect(m_gdbAdapter, SIGNAL(readyReadStandardOutput()),
this, SLOT(readGdbStandardOutput()));
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
this, SLOT(readGdbStandardError()));
connect(m_gdbAdapter, SIGNAL(adapterStarted()),
this, SLOT(handleAdapterStarted()));
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
this, SLOT(handleAdapterStartFailed(QString,QString)));
connect(m_gdbAdapter, SIGNAL(adapterShutDown()),
this, SLOT(handleAdapterShutDown()));
connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
this, SLOT(handleAdapterShutdownFailed(QString)));
connect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
this, SLOT(handleInferiorPrepared()));
connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
this, SLOT(handleInferiorStartFailed(QString)));
connect(m_gdbAdapter, SIGNAL(inferiorShutDown()),
this, SLOT(handleInferiorShutDown()));
connect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
this, SLOT(handleInferiorShutdownFailed(QString)));
connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)),
this, SLOT(handleAdapterCrashed(QString)));
@@ -265,7 +263,6 @@ void GdbEngine::initializeVariables()
m_commandsDoneCallback = 0;
m_commandsToRunOnTemporaryBreak.clear();
m_cookieForToken.clear();
m_customOutputForToken.clear();
m_pendingConsoleStreamOutput.clear();
m_pendingLogStreamOutput.clear();
@@ -561,11 +558,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
m_pendingLogStreamOutput);
response.data.setStreamOutput("consolestreamoutput",
m_pendingConsoleStreamOutput);
QByteArray custom = m_customOutputForToken[token];
if (!custom.isEmpty())
response.data.setStreamOutput("customvaluecontents",
'{' + custom + '}');
//m_customOutputForToken.remove(token);
m_pendingLogStreamOutput.clear();
m_pendingConsoleStreamOutput.clear();
@@ -581,7 +573,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
void GdbEngine::readGdbStandardError()
{
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError();
qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
}
void GdbEngine::readGdbStandardOutput()
@@ -589,7 +581,7 @@ void GdbEngine::readGdbStandardOutput()
int newstart = 0;
int scan = m_inbuffer.size();
m_inbuffer.append(m_gdbAdapter->readAllStandardOutput());
m_inbuffer.append(m_gdbProc.readAllStandardOutput());
while (newstart < m_inbuffer.size()) {
int start = newstart;
@@ -704,13 +696,13 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
}
if (cmd.flags & NeedsStop) {
if (state() == InferiorStopped || state() == AdapterStarted) {
if (state() == InferiorStopped
|| state() == InferiorStarting || state() == AdapterStarted) {
// Can be safely sent now.
flushCommand(cmd);
} else {
// Queue the commands that we cannot send at once.
showStatusMessage(tr("Stopping temporarily."), 1000);
qDebug() << _("QUEUING COMMAND ") + cmd.command;
debugMessage(_("QUEUING COMMAND ") + cmd.command);
m_commandsToRunOnTemporaryBreak.append(cmd);
interruptInferior();
@@ -896,14 +888,6 @@ void GdbEngine::handleQuerySources(const GdbResponse &response)
}
}
void GdbEngine::handleInfoShared(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
// let the modules handler do the parsing
handleModulesList(response);
}
}
#if 0
void GdbEngine::handleExecJumpToLine(const GdbResponse &response)
{
@@ -1078,7 +1062,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern);
debugMessage(_("PATTERN: ") + pat);
postCommand(_("sharedlibrary ") + pat);
continueInferior();
continueInferiorInternal();
showStatusMessage(tr("Loading %1...").arg(dataStr));
return;
}
@@ -1093,7 +1077,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// args=[],from="C:\\WINDOWS\\system32\\ntdll.dll"}
//if (reason == "signal-received"
// && data.findChild("signal-name").data() == "SIGTRAP") {
// continueInferior();
// continueInferiorInternal();
// return;
//}
@@ -1194,7 +1178,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
reloadSourceFiles();
postCommand(_("-break-list"), CB(handleBreakList));
QVariant var = QVariant::fromValue<GdbMi>(data);
postCommand(_("p 0"), CB(handleStop2), var); // dummy
postCommand(_("p 2"), CB(handleStop2), var); // dummy
} else {
#ifdef Q_OS_LINUX
// For some reason, attaching to a stopped process causes *two* stops
@@ -1205,8 +1189,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
GdbMi frameData = data.findChild("frame");
if (frameData.findChild("func").data() == "_start"
&& frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
setState(InferiorRunningRequested);
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
continueInferiorInternal();
return;
}
}
@@ -1247,9 +1230,9 @@ void GdbEngine::handleStop2(const GdbResponse &response)
void GdbEngine::handleStop2(const GdbMi &data)
{
// Sometimes we get some interesting extra information. Grab it.
GdbMi frame = data.findChild("frame");
GdbMi shortName = frame.findChild("file");
GdbMi fullName = frame.findChild("fullname");
const GdbMi gdbmiFrame = data.findChild("frame");
GdbMi shortName = gdbmiFrame.findChild("file");
GdbMi fullName = gdbmiFrame.findChild("fullname");
if (shortName.isValid() && fullName.isValid()) {
QString file = QFile::decodeName(shortName.data());
QString full = QFile::decodeName(fullName.data());
@@ -1260,16 +1243,17 @@ void GdbEngine::handleStop2(const GdbMi &data)
}
// Quick shot: Jump to stack frame #0.
if (frame.isValid()) {
const StackFrame f = parseStackFrame(frame, 0);
gotoLocation(f, true);
StackFrame frame;
if (gdbmiFrame.isValid()) {
frame = parseStackFrame(gdbmiFrame, 0);
gotoLocation(frame, true);
}
//
// Stack
//
manager()->stackHandler()->setCurrentIndex(0);
updateLocals(); // Quick shot
updateLocals(qVariantFromValue(frame)); // Quick shot
reloadStack(false);
@@ -1342,17 +1326,16 @@ void GdbEngine::handleExecContinue(const GdbResponse &response)
QTC_ASSERT(state() == InferiorRunning, /**/);
} else {
QTC_ASSERT(state() == InferiorRunningRequested, /**/);
setState(InferiorStopped);
QByteArray msg = response.data.findChild("msg").data();
if (msg.startsWith("Cannot find bounds of current function")) {
setState(InferiorStopped);
showStatusMessage(tr("Stopped."), 5000);
//showStatusMessage(tr("No debug information available. "
// "Leaving function..."));
//stepOutExec();
} else {
showMessageBox(QMessageBox::Critical, tr("Error"),
tr("Starting executable failed:\n") + QString::fromLocal8Bit(msg));
QTC_ASSERT(state() == InferiorRunning, /**/);
showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
shutdown();
}
}
@@ -1397,8 +1380,73 @@ QString GdbEngine::fullName(const QStringList &candidates)
void GdbEngine::shutdown()
{
debugMessage(_("INITIATE GDBENGINE SHUTDOWN"));
initializeVariables();
m_gdbAdapter->shutdown();
switch (state()) {
case DebuggerNotReady: // Nothing to do! :)
case EngineStarting: // We can't get here, really
case InferiorShuttingDown: // Will auto-trigger further shutdown steps
case EngineShuttingDown: // Do not disturb! :)
break;
case AdapterStarting: // GDB is up, adapter is "doing something"
setState(AdapterStartFailed);
m_gdbAdapter->shutdown();
// fall-through
case AdapterStartFailed: // Adapter "did something", but it did not help
// FIXME set some timeout?
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
break;
case InferiorRunningRequested:
case InferiorRunning:
case InferiorStopping:
case InferiorStopped:
// FIXME set some timeout?
postCommand(_(m_gdbAdapter->inferiorShutdownCommand()),
NeedsStop, CB(handleInferiorShutdown));
setState(InferiorShuttingDown); // Do it after posting the command!
break;
case AdapterStarted: // We can't get here, really
case InferiorStartFailed:
case InferiorShutDown:
case InferiorShutdownFailed: // Whatever
case InferiorUnrunnable:
// FIXME set some timeout?
postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit));
setState(EngineShuttingDown); // Do it after posting the command!
break;
case InferiorStarting: // This may take some time, so just short-circuit it
setState(InferiorStartFailed);
// fall-through
case InferiorStopFailed: // Tough luck, I guess. But unreachable as of now anyway.
setState(EngineShuttingDown);
m_gdbProc.terminate();
break;
}
}
void GdbEngine::handleInferiorShutdown(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state());
if (response.resultClass == GdbResultDone) {
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
setState(InferiorShutDown);
} else {
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
setState(InferiorShutdownFailed);
QString msg = m_gdbAdapter->msgInferiorStopFailed(_(response.data.findChild("msg").data()));
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
}
shutdown(); // re-iterate...
}
void GdbEngine::handleGdbExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultExit) {
debugMessage(_("GDB CLAIMS EXIT; WAITING"));
// don't set state here, this will be handled in handleGdbFinished()
} else {
QString msg = m_gdbAdapter->msgGdbStopFailed(_(response.data.findChild("msg").data()));
debugMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
m_gdbProc.terminate();
}
}
void GdbEngine::detachDebugger()
@@ -1414,8 +1462,7 @@ void GdbEngine::detachDebugger()
void GdbEngine::exitDebugger() // called from the manager
{
disconnectDebuggingHelperActions();
initializeVariables();
m_gdbAdapter->shutdown();
shutdown();
}
int GdbEngine::currentFrame() const
@@ -1463,6 +1510,8 @@ AbstractGdbAdapter *GdbEngine::createAdapter(const DebuggerStartParametersPtr &s
case AttachExternal:
return new AttachGdbAdapter(this);
default:
if (sp->useTerminal)
return new TermGdbAdapter(this);
return new PlainGdbAdapter(this);
}
}
@@ -1476,25 +1525,23 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
// initializeVariables());
//QTC_ASSERT(m_gdbAdapter == 0, delete m_gdbAdapter; m_gdbAdapter = 0);
initializeVariables();
m_startParameters = sp;
delete m_gdbAdapter;
m_gdbAdapter = createAdapter(sp);
connectAdapter();
if (startModeAllowsDumpers())
connectDebuggingHelperActions();
initializeVariables();
connectAdapter();
m_gdbAdapter->startAdapter();
}
void GdbEngine::continueInferiorInternal()
{
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
m_manager->resetLocation();
setTokenBarrier();
setState(InferiorRunningRequested);
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
}
@@ -1507,6 +1554,8 @@ void GdbEngine::autoContinueInferior()
void GdbEngine::continueInferior()
{
m_manager->resetLocation();
setTokenBarrier();
continueInferiorInternal();
showStatusMessage(tr("Running requested..."), 5000);
}
@@ -1589,12 +1638,10 @@ void GdbEngine::runToFunctionExec(const QString &functionName)
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
setTokenBarrier();
postCommand(_("-break-insert -t ") + functionName);
setState(InferiorRunningRequested);
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
// that should be "^running". We need to handle the resulting
// "Stopped"
postCommand(_("-exec-continue"), RunRequest, CB(handleExecContinue));
continueInferiorInternal();
//setState(InferiorRunningRequested);
//postCommand(_("-exec-continue"), handleExecRunToFunction);
showStatusMessage(tr("Run to function %1 requested...").arg(functionName), 5000);
}
void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
@@ -1903,11 +1950,7 @@ void GdbEngine::handleBreakInsert(const GdbResponse &response)
const BreakpointData *data = handler->at(index);
// Note that it is perfectly correct that the file name is put
// in quotes but not escaped. GDB simply is like that.
#if defined(Q_OS_WIN)
QFileInfo fi(data->fileName);
QString where = _c('"') + fi.fileName() + _("\":")
+ data->lineNumber;
#elif defined(Q_OS_MAC)
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
QFileInfo fi(data->fileName);
QString where = _c('"') + fi.fileName() + _("\":")
+ data->lineNumber;
@@ -2597,11 +2640,6 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos,
//
//////////////////////////////////////////////////////////////////////
//: Variable
static const QString strNotInScope =
QCoreApplication::translate("Debugger::Internal::GdbEngine", "<not in scope>");
static void setWatchDataValue(WatchData &data, const GdbMi &mi,
int encoding = 0)
{
@@ -2818,8 +2856,8 @@ void GdbEngine::updateSubItem(const WatchData &data0)
qDebug() << "FIXME: GdbEngine::updateSubItem:"
<< data.toString() << "should not happen";
#else
data.setType(strNotInScope);
data.setValue(strNotInScope);
data.setType(WatchData::msgNotInScope());
data.setValue(WatchData::msgNotInScope());
data.setHasChildren(false);
insertData(data);
return;
@@ -2964,7 +3002,7 @@ void GdbEngine::updateWatchData(const WatchData &data)
if (isSynchroneous()) {
// This should only be called for fresh expanded items, not for
// items that had their children retrieved earlier.
qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
//qDebug() << "\nUPDATE WATCH DATA: " << data.toString() << "\n";
#if 0
WatchData data1 = data;
data1.setAllUnneeded();
@@ -3153,7 +3191,7 @@ void GdbEngine::handleVarCreate(const GdbResponse &response)
} else {
data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data()));
if (data.isWatcher()) {
data.value = strNotInScope;
data.value = WatchData::msgNotInScope();
data.type = _(" ");
data.setAllUnneeded();
data.setHasChildren(false);
@@ -3206,7 +3244,7 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResponse &response)
&& msg.startsWith(__("The program being debugged stopped while"))
&& msg.contains(__("qDumpObjectData440"))) {
// Fake full stop
postCommand(_("p 0"), CB(handleStop2)); // dummy
postCommand(_("p 3"), CB(handleStop2)); // dummy
return;
}
#endif
@@ -3227,7 +3265,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResponse &response)
GdbMi contents;
if (!parseConsoleStream(response, &contents)) {
data.setError(strNotInScope);
data.setError(WatchData::msgNotInScope());
insertData(data);
return;
}
@@ -3320,7 +3358,7 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
// << " STREAM:" << out;
if (list.isEmpty()) {
//: Value for variable
data.setError(strNotInScope);
data.setError(WatchData::msgNotInScope());
data.setAllUnneeded();
insertData(data);
} else if (data.type == __("QString")
@@ -3365,19 +3403,19 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
}
} else {
//: Value for variable
data.setError(strNotInScope);
data.setError(WatchData::msgNotInScope());
data.setAllUnneeded();
insertData(data);
}
} else {
WatchData data = response.cookie.value<WatchData>();
data.setError(strNotInScope);
data.setError(WatchData::msgNotInScope());
data.setAllUnneeded();
insertData(data);
}
}
void GdbEngine::updateLocals()
void GdbEngine::updateLocals(const QVariant &cookie)
{
m_pendingRequests = 0;
m_processedNames.clear();
@@ -3398,8 +3436,8 @@ void GdbEngine::updateLocals()
postCommand(_("bb %1 %2")
.arg(int(theDebuggerBoolSetting(UseDebuggingHelpers)))
.arg(expanded.join(_(","))),
WatchUpdate, CB(handleStackFrame1));
postCommand(_("p 0"), WatchUpdate, CB(handleStackFrame2));
CB(handleStackFrame1));
postCommand(_("p 1"), CB(handleStackFrame2));
} else {
QString level = QString::number(currentFrame());
// '2' is 'list with type and value'
@@ -3407,7 +3445,7 @@ void GdbEngine::updateLocals()
postCommand(cmd, WatchUpdate, CB(handleStackListArguments));
// '2' is 'list with type and value'
postCommand(_("-stack-list-locals 2"), WatchUpdate,
CB(handleStackListLocals)); // stage 2/2
CB(handleStackListLocals), cookie); // stage 2/2
}
}
@@ -3434,7 +3472,7 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response)
out = m_firstChunk + out;
int pos = out.indexOf("locals=");
if (pos != 0) {
qDebug() << "DICARDING JUNK AT BEGIN OF RESPONSE: "
qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: "
<< out.left(pos);
out = out.mid(pos);
}
@@ -3455,7 +3493,9 @@ void GdbEngine::handleStackFrame2(const GdbResponse &response)
// qDebug() << "READ: " << list.at(i).toString();
manager()->watchHandler()->insertBulkData(list);
manager()->watchHandler()->updateWatchers();
// FIXME:
//manager()->watchHandler()->updateWatchers();
rebuildModel();
} else {
QTC_ASSERT(false, /**/);
}
@@ -3503,91 +3543,105 @@ void GdbEngine::handleStackListLocals(const GdbResponse &response)
// There could be shadowed variables
QList<GdbMi> locals = response.data.findChild("locals").children();
locals += m_currentFunctionArgs;
setLocals(locals);
QMap<QByteArray, int> seen;
// If desired, retrieve list of uninitialized variables looking at
// the current frame. This is invoked first time after a stop from
// handleStop2, which passes on the frame as cookie. The whole stack
// is not known at this point.
QStringList uninitializedVariables;
if (theDebuggerAction(UseCodeModel)->isChecked()) {
const StackFrame frame = qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) ?
qVariantValue<Debugger::Internal::StackFrame>(response.cookie) :
m_manager->stackHandler()->currentFrame();
if (frame.isUsable())
getUninitializedVariables(m_manager->cppCodeModelSnapshot(),
frame.function, frame.file, frame.line,
&uninitializedVariables);
}
QList<WatchData> list;
foreach (const GdbMi &item, locals) {
const WatchData data = localVariable(item, uninitializedVariables, &seen);
if (data.isValid())
list.push_back(data);
}
manager()->watchHandler()->insertBulkData(list);
manager()->watchHandler()->updateWatchers();
}
void GdbEngine::setLocals(const QList<GdbMi> &locals)
// Parse a local variable from GdbMi
WatchData GdbEngine::localVariable(const GdbMi &item,
const QStringList &uninitializedVariables,
QMap<QByteArray, int> *seen)
{
//qDebug() << m_varToType;
QMap<QByteArray, int> seen;
QList<WatchData> list;
foreach (const GdbMi &item, locals) {
// Local variables of inlined code are reported as
// 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
// numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..."
// We do not want these at all. Current hypotheses is that those
// "spurious" locals have _two_ "exp" field. Try to filter them:
#ifdef Q_OS_MAC
int numExps = 0;
foreach (const GdbMi &child, item.children())
numExps += int(child.name() == "exp");
if (numExps > 1)
continue;
QByteArray name = item.findChild("exp").data();
#else
QByteArray name = item.findChild("name").data();
#endif
int n = seen.value(name);
if (n) {
seen[name] = n + 1;
WatchData data;
QString nam = _(name);
data.iname = _("local.") + nam + QString::number(n + 1);
//: Variable %1 is the variable name, %2 is a simple count
data.name = tr("%1 <shadowed %2>").arg(nam).arg(n);
// Local variables of inlined code are reported as
// 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
// numchild="1",type="const QtSharedPointer::Basic<CPlusPlus::..."}}
// We do not want these at all. Current hypotheses is that those
// "spurious" locals have _two_ "exp" field. Try to filter them:
#ifdef Q_OS_MAC
int numExps = 0;
foreach (const GdbMi &child, item.children())
numExps += int(child.name() == "exp");
if (numExps > 1)
return WatchData();
QByteArray name = item.findChild("exp").data();
#else
QByteArray name = item.findChild("name").data();
#endif
const QMap<QByteArray, int>::iterator it = seen->find(name);
if (it != seen->end()) {
const int n = it.value();
++(it.value());
WatchData data;
QString nam = _(name);
data.iname = _("local.") + nam + QString::number(n + 1);
//: Variable %1 is the variable name, %2 is a simple count
data.name = WatchData::shadowedName(nam, n);
if (uninitializedVariables.contains(data.name)) {
data.setError(WatchData::msgNotInScope());
return data;
}
//: Type of local variable or parameter shadowed by another
//: variable of the same name in a nested block.
setWatchDataValue(data, item.findChild("value"));
data.setType(GdbEngine::tr("<shadowed>"));
data.setHasChildren(false);
return data;
}
seen->insert(name, 1);
WatchData data;
QString nam = _(name);
data.iname = _("local.") + nam;
data.name = nam;
data.exp = nam;
data.framekey = m_currentFrame + data.name;
setWatchDataType(data, item.findChild("type"));
if (uninitializedVariables.contains(data.name)) {
data.setError(WatchData::msgNotInScope());
return data;
}
if (isSynchroneous()) {
setWatchDataValue(data, item.findChild("value"),
item.findChild("valueencoded").data().toInt());
// We know that the complete list of children is
// somewhere in the response.
data.setChildrenUnneeded();
} else {
// set value only directly if it is simple enough, otherwise
// pass through the insertData() machinery
if (isIntOrFloatType(data.type) || isPointerType(data.type))
setWatchDataValue(data, item.findChild("value"));
if (isSymbianIntType(data.type)) {
setWatchDataValue(data, item.findChild("value"));
//: Type of local variable or parameter shadowed by another
//variable of the same name in a nested block
data.setType(tr("<shadowed>"));
data.setHasChildren(false);
list.append(data);
} else {
seen[name] = 1;
WatchData data;
QString nam = _(name);
data.iname = _("local.") + nam;
data.name = nam;
data.exp = nam;
data.framekey = m_currentFrame + data.name;
setWatchDataType(data, item.findChild("type"));
if (isSynchroneous()) {
setWatchDataValue(data, item.findChild("value"),
item.findChild("valueencoded").data().toInt());
// We know that the complete list of children is
// somewhere in the response.
data.setChildrenUnneeded();
} else {
// set value only directly if it is simple enough, otherwise
// pass through the insertData() machinery
if (isIntOrFloatType(data.type) || isPointerType(data.type))
setWatchDataValue(data, item.findChild("value"));
if (isSymbianIntType(data.type)) {
setWatchDataValue(data, item.findChild("value"));
data.setHasChildren(false);
}
}
// Let's be a bit more bold:
//if (!hasDebuggingHelperForType(data.type)) {
// QByteArray value = item.findChild("value").data();
// if (!value.isEmpty() && value != "{...}")
// data.setValue(decodeData(value, 0));
//}
if (!manager()->watchHandler()->isExpandedIName(data.iname))
data.setChildrenUnneeded();
if (isPointerType(data.type) || data.name == __("this"))
data.setHasChildren(true);
if (0 && m_varToType.contains(data.framekey)) {
qDebug() << "RE-USING" << m_varToType.value(data.framekey);
data.setType(m_varToType.value(data.framekey));
}
list.append(data);
}
}
manager()->watchHandler()->insertBulkData(list);
if (!m_manager->watchHandler()->isExpandedIName(data.iname))
data.setChildrenUnneeded();
if (isPointerType(data.type) || data.name == __("this"))
data.setHasChildren(true);
return data;
}
void GdbEngine::insertData(const WatchData &data0)
@@ -4112,9 +4166,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResponse &response)
void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
{
lastFile = frame.file;
lastLine = frame.line;
//qDebug() << "GOTO " << frame.toString() << setMarker;
// qDebug() << "GOTO " << frame << setMarker;
m_manager->gotoLocation(frame, setMarker);
}
@@ -4122,18 +4174,37 @@ void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
// Starting up & shutting down
//
void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
bool GdbEngine::startGdb(const QStringList &args, const QString &gdb)
{
setState(AdapterStartFailed);
debugMessage(_("ADAPTER START FAILED"));
Core::ICore::instance()->showWarningWithOptions(tr("Adapter start failed"), msg, QString(),
QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
shutdown();
}
debugMessage(_("STARTING GDB ") + gdb);
void GdbEngine::handleAdapterStarted()
{
debugMessage(_("ADAPTER SUCCESSFULLY STARTED, INITIALIZING GDB"));
m_gdbProc.disconnect(); // From any previous runs
QString location = gdb;
if (location.isEmpty())
location = theDebuggerStringSetting(GdbLocation);
QStringList gdbArgs;
gdbArgs << _("-i");
gdbArgs << _("mi");
gdbArgs += args;
m_gdbProc.start(location, gdbArgs);
if (!m_gdbProc.waitForStarted()) {
handleAdapterStartFailed(m_gdbProc.errorString());
return false;
}
// Do this only after the process is running, so we get no needless error notifications
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
SLOT(handleGdbError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
SLOT(readGdbStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
SLOT(readGdbStandardError()));
debugMessage(_("GDB STARTED, INITIALIZING IT"));
postCommand(_("show version"), CB(handleShowVersion));
postCommand(_("help bb"), CB(handleIsSynchroneous));
@@ -4217,20 +4288,82 @@ void GdbEngine::handleAdapterStarted()
}
}
return true;
}
void GdbEngine::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("HANDLE GDB ERROR"));
switch (error) {
case QProcess::Crashed:
break; // will get a processExited() as well
// impossible case QProcess::FailedToStart:
case QProcess::ReadError:
case QProcess::WriteError:
case QProcess::Timedout:
default:
m_gdbProc.terminate();
setState(EngineShuttingDown, true);
showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"),
errorMessage(error));
break;
}
}
void GdbEngine::handleGdbFinished(int code, QProcess::ExitStatus type)
{
debugMessage(_("GDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
if (state() == EngineShuttingDown) {
m_gdbAdapter->shutdown();
} else if (state() != AdapterStartFailed) {
showMessageBox(QMessageBox::Critical, tr("Unexpected Gdb Exit"),
tr("The gdb process exited unexpectedly (%1).")
.arg((type == QProcess::CrashExit)
? tr("crashed") : tr("code %1").arg(code)));
m_gdbAdapter->shutdown();
}
initializeVariables();
setState(DebuggerNotReady, true);
}
void GdbEngine::handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint)
{
setState(AdapterStartFailed);
debugMessage(_("ADAPTER START FAILED"));
Core::ICore::instance()->showWarningWithOptions(
tr("Adapter start failed"), msg, QString(),
_(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY), settingsIdHint);
shutdown();
}
void GdbEngine::handleAdapterStarted()
{
setState(AdapterStarted);
debugMessage(_("ADAPTER SUCCESSFULLY STARTED"));
showStatusMessage(tr("Starting inferior..."));
setState(InferiorStarting);
m_gdbAdapter->startInferior();
}
void GdbEngine::handleInferiorPrepared()
{
// Initial attempt to set breakpoints
showStatusMessage(tr("Setting breakpoints..."));
attemptBreakpointSynchronization();
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
m_commandsDoneCallback = &GdbEngine::startInferior;
if (m_cookieForToken.isEmpty()) {
startInferiorPhase2();
} else {
QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
m_commandsDoneCallback = &GdbEngine::startInferiorPhase2;
}
}
void GdbEngine::startInferior()
void GdbEngine::startInferiorPhase2()
{
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
showStatusMessage(tr("Starting inferior..."));
setState(InferiorStarting);
m_gdbAdapter->startInferior();
debugMessage(_("BREAKPOINTS SET, CONTINUING INFERIOR STARTUP"));
m_gdbAdapter->startInferiorPhase2();
}
void GdbEngine::handleInferiorStartFailed(const QString &msg)
@@ -4241,46 +4374,22 @@ void GdbEngine::handleInferiorStartFailed(const QString &msg)
shutdown();
}
void GdbEngine::handleInferiorShutDown()
{
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
}
void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
{
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
showMessageBox(QMessageBox::Critical, tr("Inferior shutdown failed"), msg);
shutdown(); // continue with adapter shutdown
}
void GdbEngine::handleAdapterCrashed(const QString &msg)
{
debugMessage(_("ADAPTER CRASHED"));
switch (state()) {
// All fall-through.
case InferiorRunning:
setState(InferiorShuttingDown);
case InferiorShuttingDown:
setState(InferiorShutDown);
case InferiorShutDown:
setState(AdapterShuttingDown);
default:
setState(DebuggerNotReady);
}
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
}
void GdbEngine::handleAdapterShutDown()
{
debugMessage(_("ADAPTER SUCCESSFULLY SHUT DOWN"));
setState(DebuggerNotReady);
}
// The adapter is expected to have cleaned up after itself when we get here,
// so the effect is about the same as AdapterStartFailed => use it.
// Don't bother with state transitions - this can happen in any state and
// the end result is always the same, so it makes little sense to find a
// "path" which does not assert.
setState(AdapterStartFailed, true);
void GdbEngine::handleAdapterShutdownFailed(const QString &msg)
{
debugMessage(_("ADAPTER SHUTDOWN FAILED"));
showMessageBox(QMessageBox::Critical, tr("Adapter shutdown failed"), msg);
setState(DebuggerNotReady);
// No point in being friendly here ...
m_gdbProc.terminate();
if (!msg.isEmpty())
showMessageBox(QMessageBox::Critical, tr("Adapter crashed"), msg);
}
void GdbEngine::addOptionPages(QList<Core::IOptionsPage*> *opts) const
@@ -4314,4 +4423,3 @@ IDebuggerEngine *createGdbEngine(DebuggerManager *manager)
Q_DECLARE_METATYPE(Debugger::Internal::MemoryAgentCookie);
Q_DECLARE_METATYPE(Debugger::Internal::DisassemblerAgentCookie);
Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);

View File

@@ -92,84 +92,79 @@ private:
friend class AttachGdbAdapter;
friend class CoreGdbAdapter;
friend class PlainGdbAdapter;
friend class TermGdbAdapter;
friend class RemoteGdbAdapter;
friend class TrkGdbAdapter;
//
// IDebuggerEngine implementation
//
void stepExec();
void stepOutExec();
void nextExec();
void stepIExec();
void nextIExec();
private: ////////// General Interface //////////
void shutdown();
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
void startDebugger(const DebuggerStartParametersPtr &sp);
void exitDebugger();
void detachDebugger();
virtual void addOptionPages(QList<Core::IOptionsPage*> *opts) const;
void continueInferiorInternal();
void autoContinueInferior();
void continueInferior();
void interruptInferior();
virtual bool checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage= 0) const;
void runToLineExec(const QString &fileName, int lineNumber);
void runToFunctionExec(const QString &functionName);
void jumpToLineExec(const QString &fileName, int lineNumber);
virtual bool isGdbEngine() const { return true; }
void activateFrame(int index);
void selectThread(int index);
virtual void startDebugger(const DebuggerStartParametersPtr &sp);
virtual void exitDebugger();
virtual void detachDebugger();
virtual void shutdown();
Q_SLOT void attemptBreakpointSynchronization();
virtual void executeDebuggerCommand(const QString &command);
void assignValueInDebugger(const QString &expr, const QString &value);
void executeDebuggerCommand(const QString & command);
void watchPoint(const QPoint &);
private: ////////// General State //////////
void loadSymbols(const QString &moduleName);
void loadAllSymbols();
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
void fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length);
void handleFetchMemory(const GdbResponse &response);
void fetchDisassembler(DisassemblerViewAgent *agent,
const StackFrame &frame);
void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
bool useMixedMode);
void handleFetchDisassemblerByLine(const GdbResponse &response);
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
Q_SLOT void setAutoDerefPointers(const QVariant &on);
bool isGdbEngine() const { return true; }
bool isSynchroneous() const;
bool checkConfiguration(int toolChain, QString *errorMessage, QString *settingsPage= 0) const;
//
// Own stuff
//
int currentFrame() const;
bool supportsThreads() const;
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
StackFrame parseStackFrame(const GdbMi &mi, int level);
void connectAdapter();
void initializeVariables();
QString fullName(const QString &fileName);
// get one usable name out of these, try full names first
QString fullName(const QStringList &candidates);
DebuggerStartMode startMode() const;
const DebuggerStartParameters &startParameters() const
{ return *m_startParameters; }
Q_SLOT void setAutoDerefPointers(const QVariant &on);
void handleResult(const GdbResponse &response);
DebuggerStartParametersPtr m_startParameters;
QSharedPointer<TrkOptions> m_trkOptions;
public: // otherwise the Qt flag macros are unhappy
private: ////////// Gdb Process Management //////////
AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp);
void connectAdapter();
bool startGdb(const QStringList &args = QStringList(), const QString &gdb = QString());
void startInferiorPhase2();
void handleInferiorShutdown(const GdbResponse &response);
void handleGdbExit(const GdbResponse &response);
void gdbInputAvailable(int channel, const QString &msg)
{ m_manager->showDebuggerInput(channel, msg); }
void gdbOutputAvailable(int channel, const QString &msg)
{ m_manager->showDebuggerOutput(channel, msg); }
private slots:
void handleGdbFinished(int, QProcess::ExitStatus status);
void handleGdbError(QProcess::ProcessError error);
void readGdbStandardOutput();
void readGdbStandardError();
void readDebugeeOutput(const QByteArray &data);
void handleAdapterStarted();
void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
void handleInferiorPrepared();
void handleInferiorStartFailed(const QString &msg);
void handleAdapterCrashed(const QString &msg);
private:
QTextCodec *m_outputCodec;
QTextCodec::ConverterState m_outputCodecState;
QByteArray m_inbuffer;
QProcess m_gdbProc;
AbstractGdbAdapter *m_gdbAdapter;
private: ////////// Gdb Command Management //////////
public: // otherwise the Qt flag macros are unhappy
enum GdbCommandFlag {
NoFlags = 0,
NeedsStop = 1, // The command needs a stopped inferior
@@ -181,9 +176,8 @@ public: // otherwise the Qt flag macros are unhappy
ExitRequest = 32 // Callback expect GdbResultExit instead of GdbResultDone
};
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
private:
private:
typedef void (GdbEngine::*GdbCommandCallback)
(const GdbResponse &response);
typedef void (AbstractGdbAdapter::*AdapterCallback)
@@ -230,65 +224,7 @@ private:
void postCommandHelper(const GdbCommand &cmd);
void setTokenBarrier();
void updateAll();
void updateLocals();
void gdbInputAvailable(int channel, const QString &msg)
{ m_manager->showDebuggerInput(channel, msg); }
void gdbOutputAvailable(int channel, const QString &msg)
{ m_manager->showDebuggerOutput(channel, msg); }
private slots:
void readGdbStandardOutput();
void readGdbStandardError();
void readDebugeeOutput(const QByteArray &data);
void handleAdapterStarted();
void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
void handleInferiorStartFailed(const QString &msg);
void handleInferiorShutDown();
void handleInferiorShutdownFailed(const QString &msg);
void handleAdapterCrashed(const QString &msg);
void handleAdapterShutDown();
void handleAdapterShutdownFailed(const QString &msg);
private:
int terminationIndex(const QByteArray &buffer, int &length);
void handleResponse(const QByteArray &buff);
void handleStopResponse(const GdbMi &data);
void handleStop1(const GdbResponse &response);
void handleStop1(const GdbMi &data);
void handleStop2(const GdbResponse &response);
void handleStop2(const GdbMi &data);
void handleResultRecord(const GdbResponse &response);
void handleExecContinue(const GdbResponse &response);
// void handleExecRunToFunction(const GdbResponse &response);
void handleInfoShared(const GdbResponse &response);
void handleShowVersion(const GdbResponse &response);
void handleQuerySources(const GdbResponse &response);
void handleWatchPoint(const GdbResponse &response);
void handleIsSynchroneous(const GdbResponse &response);
bool showToolTip();
// Convenience
QMainWindow *mainWindow() const;
DebuggerStartMode startMode() const;
qint64 inferiorPid() const { return m_manager->inferiorPid(); }
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
void handleChildren(const WatchData &parent, const GdbMi &child,
QList<WatchData> *insertions);
const bool m_dumperInjectionLoad;
QTextCodec *m_outputCodec;
QTextCodec::ConverterState m_outputCodecState;
QByteArray m_inbuffer;
QHash<int, GdbCommand> m_cookieForToken;
QHash<int, QByteArray> m_customOutputForToken;
QByteArray m_pendingConsoleStreamOutput;
QByteArray m_pendingLogStreamOutput;
@@ -298,13 +234,68 @@ private:
// out of date and discarded.
int m_oldestAcceptableToken;
int m_pendingRequests; // Watch updating commands in flight
typedef void (GdbEngine::*CommandsDoneCallback)();
// function called after all previous responses have been received
CommandsDoneCallback m_commandsDoneCallback;
QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
private: ////////// Gdb Output, State & Capability Handling //////////
void handleResponse(const QByteArray &buff);
void handleStopResponse(const GdbMi &data);
void handleResultRecord(const GdbResponse &response);
void handleStop1(const GdbResponse &response);
void handleStop1(const GdbMi &data);
void handleStop2(const GdbResponse &response);
void handleStop2(const GdbMi &data);
StackFrame parseStackFrame(const GdbMi &mi, int level);
virtual bool isSynchroneous() const;
bool supportsThreads() const;
// Gdb initialization sequence
void handleShowVersion(const GdbResponse &response);
void handleIsSynchroneous(const GdbResponse &response);
int m_gdbVersion; // 6.8.0 is 680
int m_gdbBuildVersion; // MAC only?
bool m_isSynchroneous; // Can act synchroneously?
// awful hack to keep track of used files
QMap<QString, QString> m_shortToFullName;
QMap<QString, QString> m_fullToShortName;
private: ////////// Inferior Management //////////
Q_SLOT virtual void attemptBreakpointSynchronization();
virtual void stepExec();
virtual void stepOutExec();
virtual void nextExec();
virtual void stepIExec();
virtual void nextIExec();
void continueInferiorInternal();
void autoContinueInferior();
virtual void continueInferior();
virtual void interruptInferior();
virtual void runToLineExec(const QString &fileName, int lineNumber);
virtual void runToFunctionExec(const QString &functionName);
// void handleExecRunToFunction(const GdbResponse &response);
virtual void jumpToLineExec(const QString &fileName, int lineNumber);
void handleExecContinue(const GdbResponse &response);
qint64 inferiorPid() const { return m_manager->inferiorPid(); }
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
void maybeHandleInferiorPidChanged(const QString &pid);
private: ////////// View & Data Stuff //////////
virtual void selectThread(int index);
virtual void activateFrame(int index);
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
//
// Breakpoint specific stuff
@@ -323,9 +314,13 @@ private:
//
// Modules specific stuff
//
virtual void loadSymbols(const QString &moduleName);
virtual void loadAllSymbols();
virtual QList<Symbol> moduleSymbols(const QString &moduleName);
void reloadModules();
void handleModulesList(const GdbResponse &response);
bool m_modulesListOutdated;
//
// Register specific stuff
@@ -335,54 +330,83 @@ private:
void handleRegisterListNames(const GdbResponse &response);
void handleRegisterListValues(const GdbResponse &response);
//
// Disassembler specific stuff
//
virtual void fetchDisassembler(DisassemblerViewAgent *agent,
const StackFrame &frame);
void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
bool useMixedMode);
void handleFetchDisassemblerByLine(const GdbResponse &response);
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
QString parseDisassembler(const GdbMi &lines);
//
// Source file specific stuff
//
void reloadSourceFiles();
void handleQuerySources(const GdbResponse &response);
QString fullName(const QString &fileName);
// get one usable name out of these, try full names first
QString fullName(const QStringList &candidates);
// awful hack to keep track of used files
QMap<QString, QString> m_shortToFullName;
QMap<QString, QString> m_fullToShortName;
//
// Stack specific stuff
//
void updateAll();
void handleStackListFrames(const GdbResponse &response);
void handleStackSelectThread(const GdbResponse &response);
void handleStackListThreads(const GdbResponse &response);
void handleStackFrame1(const GdbResponse &response);
void handleStackFrame2(const GdbResponse &response);
QByteArray m_firstChunk;
Q_SLOT void reloadStack(bool forceGotoLocation);
Q_SLOT void reloadFullStack();
int currentFrame() const;
//
// Tooltip specific stuff
//
void sendToolTipCommand(const QString &command, const QString &cookie);
QList<GdbMi> m_currentFunctionArgs;
QByteArray m_firstChunk;
QString m_currentFrame;
//
// Watch specific stuff
//
virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
virtual void assignValueInDebugger(const QString &expr, const QString &value);
virtual void fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length);
void handleFetchMemory(const GdbResponse &response);
virtual void watchPoint(const QPoint &);
void handleWatchPoint(const GdbResponse &response);
// FIXME: BaseClass. called to improve situation for a watch item
void updateSubItem(const WatchData &data);
void handleChildren(const WatchData &parent, const GdbMi &child,
QList<WatchData> *insertions);
void updateWatchData(const WatchData &data);
Q_SLOT void updateWatchDataHelper(const WatchData &data);
void rebuildModel();
bool showToolTip();
void insertData(const WatchData &data);
void sendWatchParameters(const QByteArray &params0);
void createGdbVariable(const WatchData &data);
void maybeHandleInferiorPidChanged(const QString &pid);
void tryLoadDebuggingHelpers();
void tryQueryDebuggingHelpers();
Q_SLOT void recheckDebuggingHelperAvailability();
void runDebuggingHelper(const WatchData &data, bool dumpChildren);
void runDirectDebuggingHelper(const WatchData &data, bool dumpChildren);
bool hasDebuggingHelperForType(const QString &type) const;
void handleVarListChildren(const GdbResponse &response);
void handleVarListChildrenHelper(const GdbMi &child,
const WatchData &parent);
void handleVarCreate(const GdbResponse &response);
void handleVarAssign(const GdbResponse &response);
void handleEvaluateExpression(const GdbResponse &response);
@@ -393,53 +417,42 @@ private:
void handleDebuggingHelperValue3(const GdbResponse &response);
void handleDebuggingHelperEditValue(const GdbResponse &response);
void handleDebuggingHelperSetup(const GdbResponse &response);
void updateLocals(const QVariant &cookie = QVariant());
void handleStackListLocals(const GdbResponse &response);
WatchData localVariable(const GdbMi &item,
const QStringList &uninitializedVariables,
QMap<QByteArray, int> *seen);
void setLocals(const QList<GdbMi> &locals);
void handleStackListArguments(const GdbResponse &response);
void handleVarListChildrenHelper(const GdbMi &child,
const WatchData &parent);
void setWatchDataType(WatchData &data, const GdbMi &mi);
void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);
void setLocals(const QList<GdbMi> &locals);
void connectDebuggingHelperActions();
void disconnectDebuggingHelperActions();
AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp);
bool startModeAllowsDumpers() const;
QString parseDisassembler(const GdbMi &lines);
int m_pendingRequests;
QSet<QString> m_processedNames;
QtDumperHelper m_dumperHelper;
DebuggingHelperState m_debuggingHelperState;
QList<GdbMi> m_currentFunctionArgs;
QString m_currentFrame;
QMap<QString, QString> m_varToType;
typedef void (GdbEngine::*CommandsDoneCallback)();
// function called after all previous responses have been received
CommandsDoneCallback m_commandsDoneCallback;
void startInferior();
private: ////////// Dumper Management //////////
bool m_modulesListOutdated;
bool startModeAllowsDumpers() const;
void tryLoadDebuggingHelpers();
void tryQueryDebuggingHelpers();
Q_SLOT void recheckDebuggingHelperAvailability();
void connectDebuggingHelperActions();
void disconnectDebuggingHelperActions();
Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
const bool m_dumperInjectionLoad;
DebuggingHelperState m_debuggingHelperState;
QtDumperHelper m_dumperHelper;
DebuggerStartParametersPtr m_startParameters;
// make sure to re-initialize new members in initializeVariables();
private: ////////// Convenience Functions //////////
QSharedPointer<TrkOptions> m_trkOptions;
AbstractGdbAdapter *m_gdbAdapter;
public:
QString errorMessage(QProcess::ProcessError error);
void showMessageBox(int icon, const QString &title, const QString &text);
void debugMessage(const QString &msg);
void addOptionPages(QList<Core::IOptionsPage*> *opts) const;
const DebuggerStartParameters &startParameters() const
{ return *m_startParameters; }
QMainWindow *mainWindow() const;
};
} // namespace Internal

View File

@@ -29,18 +29,13 @@
#include "plaingdbadapter.h"
#include "debuggeractions.h"
#include "gdbengine.h"
#include "procinterrupt.h"
#include "debuggerstringutils.h"
#include <utils/qtcassert.h>
#include <utils/fancymainwindow.h>
#include <coreplugin/icore.h>
#include <QtCore/QFileInfo>
#include <QtCore/QVariant>
#include <QtGui/QMessageBox>
namespace Debugger {
namespace Internal {
@@ -58,8 +53,6 @@ namespace Internal {
PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent)
{
commonInit();
// Output
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
engine, SLOT(readDebugeeOutput(QByteArray)));
@@ -72,37 +65,27 @@ void PlainGdbAdapter::startAdapter()
debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs;
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
if (!m_outputCollector.listen()) {
emit adapterStartFailed(tr("Cannot set up communication with child process: %1")
.arg(m_outputCollector.errorString()), QString());
return;
}
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
gdbArgs.append(_("--tty=") + m_outputCollector.serverName());
if (!startParameters().workingDir.isEmpty())
m_gdbProc.setWorkingDirectory(startParameters().workingDir);
m_engine->m_gdbProc.setWorkingDirectory(startParameters().workingDir);
if (!startParameters().environment.isEmpty())
m_gdbProc.setEnvironment(startParameters().environment);
m_engine->m_gdbProc.setEnvironment(startParameters().environment);
m_gdbProc.start(theDebuggerStringSetting(GdbLocation), gdbArgs);
}
if (!m_engine->startGdb(gdbArgs)) {
m_outputCollector.shutdown();
return;
}
void PlainGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit adapterStarted();
}
void PlainGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("PLAIN ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
}
void PlainGdbAdapter::startInferior()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
@@ -118,9 +101,7 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultDone) {
//m_breakHandler->clearBreakMarkers();
setState(InferiorRunningRequested);
m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
emit inferiorPrepared();
} else {
QString msg = tr("Starting executable failed:\n") +
__(response.data.findChild("msg").data());
@@ -128,6 +109,12 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
}
}
void PlainGdbAdapter::startInferiorPhase2()
{
setState(InferiorRunningRequested);
m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
}
void PlainGdbAdapter::handleExecRun(const GdbResponse &response)
{
if (response.resultClass == GdbResultRunning) {
@@ -160,74 +147,6 @@ void PlainGdbAdapter::shutdown()
{
debugMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
m_outputCollector.shutdown();
switch (state()) {
case InferiorRunningRequested:
case InferiorRunning:
case InferiorStopping:
case InferiorStopped:
setState(InferiorShuttingDown);
m_engine->postCommand(_("kill"), CB(handleKill));
return;
case InferiorShuttingDown:
// FIXME: How can we end up here?
QTC_ASSERT(false, qDebug() << state());
// Fall through.
case InferiorShutDown:
setState(AdapterShuttingDown);
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
return;
/*
case InferiorShutdownFailed:
m_gdbProc.terminate();
// 20s can easily happen when loading webkit debug information
m_gdbProc.waitForFinished(20000);
setState(AdapterShuttingDown);
debugMessage(_("FORCING TERMINATION: %1").arg(state()));
if (state() != QProcess::NotRunning) {
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
.arg(state()));
m_gdbProc.kill();
}
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
return;
*/
default:
QTC_ASSERT(false, qDebug() << state());
}
}
void PlainGdbAdapter::handleKill(const GdbResponse &response)
{
debugMessage(_("PLAIN ADAPTER HANDLE KILL " + response.toString()));
if (response.resultClass == GdbResultDone) {
setState(InferiorShutDown);
emit inferiorShutDown();
shutdown(); // re-iterate...
} else {
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
setState(InferiorShutdownFailed);
emit inferiorShutdownFailed(msg);
}
}
void PlainGdbAdapter::handleExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
// don't set state here, this will be handled in handleGdbFinished()
} else {
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
emit adapterShutdownFailed(msg);
}
}
void PlainGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
{
debugMessage(_("GDB PROCESS FINISHED"));
emit adapterShutDown();
}
} // namespace Internal

View File

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

View File

@@ -28,8 +28,8 @@
**************************************************************************/
#include "remotegdbadapter.h"
#include "debuggerstringutils.h"
#include "debuggeractions.h"
#include "gdbengine.h"
#include <utils/qtcassert.h>
@@ -54,8 +54,6 @@ namespace Internal {
RemoteGdbAdapter::RemoteGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent)
{
commonInit();
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(uploadProcError(QProcess::ProcessError)));
connect(&m_uploadProc, SIGNAL(readyReadStandardOutput()),
@@ -70,14 +68,6 @@ void RemoteGdbAdapter::startAdapter()
setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs;
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
QString location = startParameters().debuggerCommand;
if (location.isEmpty())
location = theDebuggerStringSetting(GdbLocation);
// FIXME: make asynchroneous
// Start the remote server
if (startParameters().serverStartScript.isEmpty()) {
@@ -88,33 +78,19 @@ void RemoteGdbAdapter::startAdapter()
m_uploadProc.waitForStarted();
}
// Start the debugger
m_gdbProc.start(location, gdbArgs);
}
if (!m_engine->startGdb(QStringList(), startParameters().debuggerCommand))
// FIXME: cleanup missing
return;
void RemoteGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit adapterStarted();
}
void RemoteGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
debugMessage(_("ADAPTER, HANDLE GDB ERROR"));
emit adapterCrashed(m_engine->errorMessage(error));
shutdown();
}
void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
{
QString msg;
switch (error) {
case QProcess::FailedToStart:
msg = tr("The upload process failed to start. Either the "
"invoked script '%1' is missing, or you may have insufficient "
"permissions to invoke the program.")
.arg(theDebuggerStringSetting(GdbLocation));
msg = tr("The upload process failed to start. Shell missing?");
break;
case QProcess::Crashed:
msg = tr("The upload process crashed some time after starting "
@@ -140,7 +116,7 @@ void RemoteGdbAdapter::uploadProcError(QProcess::ProcessError error)
}
m_engine->showStatusMessage(msg);
QMessageBox::critical(m_engine->mainWindow(), tr("Error"), msg);
showMessageBox(QMessageBox::Critical, tr("Error"), msg);
}
void RemoteGdbAdapter::readUploadStandardOutput()
@@ -211,7 +187,7 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
// gdb server will stop the remote application itself.
debugMessage(_("INFERIOR STARTED"));
showStatusMessage(msgAttachedToStoppedInferior());
m_engine->continueInferior();
emit inferiorPrepared();
} else {
// 16^error,msg="hd:5555: Connection timed out."
QString msg = msgConnectRemoteServerFailed(__(record.data.findChild("msg").data()));
@@ -219,6 +195,11 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
}
}
void RemoteGdbAdapter::startInferiorPhase2()
{
m_engine->continueInferiorInternal();
}
void RemoteGdbAdapter::interruptInferior()
{
m_engine->postCommand(_("-exec-interrupt"));
@@ -226,56 +207,7 @@ void RemoteGdbAdapter::interruptInferior()
void RemoteGdbAdapter::shutdown()
{
switch (state()) {
case InferiorRunning:
case InferiorStopped:
setState(InferiorShuttingDown);
m_engine->postCommand(_("kill"), CB(handleKill));
return;
default:
QTC_ASSERT(false, qDebug() << state());
// fall through
case InferiorStartFailed:
case InferiorShutDown:
setState(AdapterShuttingDown);
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
return;
}
}
void RemoteGdbAdapter::handleKill(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorShuttingDown, qDebug() << state());
if (response.resultClass == GdbResultDone) {
setState(InferiorShutDown);
emit inferiorShutDown();
shutdown(); // re-iterate...
} else {
QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
setState(InferiorShutdownFailed);
emit inferiorShutdownFailed(msg);
}
}
void RemoteGdbAdapter::handleExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
// don't set state here, this will be handled in handleGdbFinished()
} else {
QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
emit adapterShutdownFailed(msg);
}
}
void RemoteGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
{
debugMessage(_("GDB PROESS FINISHED"));
setState(DebuggerNotReady);
emit adapterShutDown();
// FIXME: cleanup missing
}
} // namespace Internal

View File

@@ -31,10 +31,6 @@
#define DEBUGGER_REMOTEGDBADAPTER_H
#include "abstractgdbadapter.h"
#include "gdbengine.h"
#include <QtCore/QDebug>
#include <QtCore/QProcess>
namespace Debugger {
namespace Internal {
@@ -56,6 +52,7 @@ public:
void startAdapter();
void startInferior();
void startInferiorPhase2();
void interruptInferior();
void shutdown();
@@ -67,12 +64,6 @@ private:
void handleSetTargetAsync(const GdbResponse &response);
void handleFileExecAndSymbols(const GdbResponse &response);
void handleTargetRemote(const GdbResponse &response);
void handleKill(const GdbResponse &response);
void handleExit(const GdbResponse &response);
Q_SLOT void handleGdbStarted();
Q_SLOT void handleGdbError(QProcess::ProcessError error);
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
QProcess m_uploadProc;
};

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 "trkoptions.h"
#include "trkoptionspage.h"
#include "debuggerstringutils.h"
#ifndef STANDALONE_RUNNER
#include "gdbengine.h"
#endif
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <sys/types.h>
# include <unistd.h>
#endif
#include <utils/qtcassert.h>
#include <QtCore/QTimer>
#include <QtCore/QDir>
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <sys/types.h>
# include <unistd.h>
#endif
#define CB(callback) \
static_cast<GdbEngine::AdapterCallback>(&TrkGdbAdapter::callback), \
STRINGIFY(callback)
@@ -204,10 +206,6 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
#endif
m_gdbServerName = _("127.0.0.1:%1").arg(2222 + portOffset);
commonInit();
connect(&m_gdbProc, SIGNAL(stateChanged(QProcess::ProcessState)),
this, SLOT(handleGdbStateChanged(QProcess::ProcessState)));
connect(&m_rfcommProc, SIGNAL(readyReadStandardError()),
this, SLOT(handleRfcommReadyReadStandardError()));
connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()),
@@ -380,17 +378,6 @@ QByteArray TrkGdbAdapter::trkInterruptMessage()
return ba;
}
void TrkGdbAdapter::emitDelayedAdapterStartFailed(const QString &msg)
{
m_adapterFailMessage = msg;
QTimer::singleShot(0, this, SLOT(slotEmitDelayedAdapterStartFailed()));
}
void TrkGdbAdapter::slotEmitDelayedAdapterStartFailed()
{
emit adapterStartFailed(m_adapterFailMessage, TrkOptionsPage::settingsId());
}
void TrkGdbAdapter::emitDelayedInferiorStartFailed(const QString &msg)
{
m_adapterFailMessage = msg;
@@ -428,6 +415,7 @@ void TrkGdbAdapter::waitForTrkConnect()
}
m_trkDevice.sendTrkInitialPing();
sendTrkMessage(0x02); // Disconnect, as trk might be still connected
sendTrkMessage(0x01); // Connect
sendTrkMessage(0x05, TrkCB(handleSupportMask));
sendTrkMessage(0x06, TrkCB(handleCpuType));
@@ -437,7 +425,7 @@ void TrkGdbAdapter::waitForTrkConnect()
// "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
//sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
maybeAdapterStarted();
emit adapterStarted();
}
void TrkGdbAdapter::logMessage(const QString &msg)
@@ -1527,52 +1515,6 @@ void TrkGdbAdapter::interruptInferior()
sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
}
void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error)
{
if (error == QProcess::FailedToStart) {
const QString msg = QString::fromLatin1("GDB: Cannot start '%1': %2. Please check the settings.").arg(m_options->gdb).arg(m_gdbProc.errorString());
emitDelayedAdapterStartFailed(msg); // Emitted from QProcess::start() on Windows
} else {
// Others should trigger handleGdbFinished
const QString msg = QString::fromLatin1("GDB: Process error %1: %2").arg(error).arg(m_gdbProc.errorString());
logMessage(msg);
}
}
void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
const QString msg = exitStatus == QProcess::NormalExit ?
QString::fromLatin1("GDB: Process finished (exit code: %1).").arg(exitCode) :
QString::fromLatin1("GDB: Process crashed: %1").arg(m_gdbProc.errorString());
if (state() == AdapterStarting) {
emitDelayedAdapterStartFailed(msg);// Potentially emitted from QProcess::start() on Windows
} else {
logMessage(msg);
setState(DebuggerNotReady);
emit adapterShutDown();
}
}
void TrkGdbAdapter::handleGdbStarted()
{
logMessage(QString("GDB: Process Started"));
maybeAdapterStarted();
}
void TrkGdbAdapter::maybeAdapterStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
if (m_gdbProc.state() == QProcess::Running && m_trkDevice.isOpen()) {
setState(AdapterStarted);
emit adapterStarted();
}
}
void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState)
{
logMessage(_("GDB: Process State %1").arg(newState));
}
void TrkGdbAdapter::startAdapter()
{
// Retrieve parameters
@@ -1634,13 +1576,12 @@ void TrkGdbAdapter::startAdapter()
connect(m_gdbServer, SIGNAL(newConnection()),
this, SLOT(handleGdbConnection()));
logMessage("STARTING GDB");
logMessage(_("### Starting gdb %1").arg(m_options->gdb));
QStringList gdbArgs;
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
gdbArgs.append(QLatin1String("-i"));
gdbArgs.append(QLatin1String("mi"));
m_gdbProc.start(m_options->gdb, gdbArgs);
if (!m_engine->startGdb(gdbArgs, m_options->gdb)) {
cleanup();
return;
}
waitForTrkConnect();
}
@@ -1701,8 +1642,7 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (record.resultClass == GdbResultDone) {
setState(InferiorRunningRequested);
m_engine->postCommand(_("-exec-continue"), GdbEngine::RunRequest, CB(handleFirstContinue));
emit inferiorPrepared();
} else {
QString msg = tr("Connecting to trk server adapter failed:\n")
+ _(record.data.findChild("msg").data());
@@ -1710,15 +1650,9 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
}
}
void TrkGdbAdapter::handleFirstContinue(const GdbResponse &record)
void TrkGdbAdapter::startInferiorPhase2()
{
QTC_ASSERT(state() == InferiorRunning, qDebug() << state());
if (record.resultClass == GdbResultDone) {
debugMessage(_("INFERIOR STARTED"));
showStatusMessage(msgInferiorRunning());
} else {
emit inferiorStartFailed(msgConnectRemoteServerFailed(record.toString()));
}
m_engine->continueInferiorInternal();
}
//
@@ -1794,7 +1728,7 @@ void TrkGdbAdapter::write(const QByteArray &data)
trkReadMemoryMessage(m_session.dataseg, 12));
return;
}
m_gdbProc.write(data);
m_engine->m_gdbProc.write(data);
}
uint oldPC;
@@ -1992,79 +1926,7 @@ void TrkGdbAdapter::cleanup()
void TrkGdbAdapter::shutdown()
{
switch (state()) {
case AdapterStarting:
case AdapterStartFailed:
cleanup();
setState(DebuggerNotReady);
return;
case InferiorStopping:
case InferiorRunningRequested:
case InferiorRunning:
//sendTrkMessage(0x1a, TrkCallback(), trkInterruptMessage(), "Interrupting...");
// Fall through.
case InferiorStopped:
//sendTrkMessage(0x41, TrkCallback(), trkDeleteProcessMessage(), "Delete process");
//sendTrkMessage(0x02, TrkCB(handleDisconnect));
setState(InferiorShuttingDown);
m_engine->postCommand(_("kill"), CB(handleKill));
return;
case InferiorShutDown:
setState(AdapterShuttingDown);
cleanup();
m_engine->postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleExit));
return;
/*
if (m_options->mode == TrkOptions::BlueTooth
&& m_rfcommProc.state() == QProcess::Running)
m_rfcommProc.kill();
m_rfcommProc.terminate();
m_rfcommProc.write(ba);
m_rfcommProc.terminate();
m_rfcommProc.waitForFinished();
m_gdbProc.kill();
m_gdbProc.terminate();
QByteArray ba;
ba.append(0x03);
QProcess proc;
proc.start("rfcomm release " + m_options->blueToothDevice);
proc.waitForFinished();
m_gdbProc.waitForFinished(msecs);
*/
default:
QTC_ASSERT(false, qDebug() << state());
}
}
void TrkGdbAdapter::handleKill(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
setState(InferiorShutDown);
emit inferiorShutDown();
shutdown(); // re-iterate...
} else {
const QString msg = msgInferiorStopFailed(__(response.data.findChild("msg").data()));
setState(InferiorShutdownFailed);
emit inferiorShutdownFailed(msg);
}
}
void TrkGdbAdapter::handleExit(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
qDebug() << "EXITED, NO MESSAGE...";
// don't set state here, this will be handled in handleGdbFinished()
} else {
const QString msg = msgGdbStopFailed(__(response.data.findChild("msg").data()));
emit adapterShutdownFailed(msg);
}
cleanup();
}
} // namespace Internal

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -105,6 +105,7 @@ WatchData::WatchData() :
generation(-1),
valueEnabled(true),
valueEditable(true),
error(false),
source(0),
state(InitialState),
changed(false)
@@ -127,7 +128,8 @@ bool WatchData::isEqual(const WatchData &other) const
&& framekey == other.framekey
&& hasChildren == other.hasChildren
&& valueEnabled == other.valueEnabled
&& valueEditable == other.valueEditable;
&& valueEditable == other.valueEditable
&& error == other.error;
}
void WatchData::setError(const QString &msg)
@@ -137,6 +139,7 @@ void WatchData::setError(const QString &msg)
setHasChildren(false);
valueEnabled = false;
valueEditable = false;
error = true;
}
void WatchData::setValue(const QString &value0)
@@ -232,6 +235,8 @@ QString WatchData::toString() const
str << "iname=\"" << iname << doubleQuoteComma;
if (!name.isEmpty() && name != iname)
str << "name=\"" << name << doubleQuoteComma;
if (error)
str << "error,";
if (!addr.isEmpty())
str << "addr=\"" << addr << doubleQuoteComma;
if (!exp.isEmpty())
@@ -310,6 +315,19 @@ QString WatchData::toToolTip() const
return res;
}
QString WatchData::msgNotInScope()
{
static const QString rc = QCoreApplication::translate("Debugger::Internal::WatchData", "<not in scope>");
return rc;
}
QString WatchData::shadowedName(const QString &name, int seen)
{
if (seen <= 0)
return name;
return QCoreApplication::translate("Debugger::Internal::WatchData", "%1 <shadowed %2>").arg(name).arg(seen);
}
///////////////////////////////////////////////////////////////////////
//
// WatchModel
@@ -590,9 +608,10 @@ void WatchModel::fetchMore(const QModelIndex &index)
QTC_ASSERT(index.isValid(), return);
QTC_ASSERT(!watchItem(index)->fetchTriggered, return);
if (WatchItem *item = watchItem(index)) {
m_handler->m_expandedINames.insert(item->iname);
item->fetchTriggered = true;
WatchData data = *item;
if (item->children.isEmpty()) {
WatchData data = *item;
data.setChildrenNeeded();
m_handler->m_manager->updateWatchData(data);
}
@@ -771,10 +790,13 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
{
WatchItem &data = *watchItem(index);
if (role == ExpandedRole) {
if (value.toBool())
if (value.toBool()) {
// Should already have been triggered by fetchMore()
QTC_ASSERT(m_handler->m_expandedINames.contains(data.iname), /**/);
m_handler->m_expandedINames.insert(data.iname);
else
} else {
m_handler->m_expandedINames.remove(data.iname);
}
} else if (role == TypeFormatRole) {
m_handler->setFormat(data.type, value.toInt());
} else if (role == IndividualFormatRole) {

View File

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

View File

@@ -43,6 +43,9 @@
#include <cpptools/cpptoolsconstants.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/Overview.h>
#include <Symbols.h>
#include <Scope.h>
#include <extensionsystem/pluginmanager.h>
@@ -51,6 +54,7 @@
#include <QtCore/QStringList>
#include <QtCore/QCoreApplication>
#include <QtCore/QTextStream>
#include <QtCore/QHash>
#include <QtGui/QTextCursor>
#include <QtGui/QPlainTextEdit>
@@ -59,6 +63,78 @@
#include <ctype.h>
enum { debug = 0 };
// Debug helpers for code model. @todo: Move to some CppTools library?
namespace CPlusPlus {
static void debugCppSymbolRecursion(QTextStream &str, const Overview &o,
const Symbol &s, bool doRecurse = true,
int recursion = 0)
{
for (int i = 0; i < recursion; i++)
str << " ";
str << "Symbol: " << o.prettyName(s.name()) << " at line " << s.line();
if (s.isFunction())
str << " function";
if (s.isClass())
str << " class";
if (s.isDeclaration())
str << " declaration";
if (s.isBlock())
str << " block";
if (doRecurse && s.isScopedSymbol()) {
const ScopedSymbol *scoped = s.asScopedSymbol();
const int size = scoped->memberCount();
str << " scoped symbol of " << size << '\n';
for (int m = 0; m < size; m++)
debugCppSymbolRecursion(str, o, *scoped->memberAt(m), true, recursion + 1);
} else {
str << '\n';
}
}
QDebug operator<<(QDebug d, const Symbol &s)
{
QString output;
CPlusPlus::Overview o;
QTextStream str(&output);
debugCppSymbolRecursion(str, o, s, true, 0);
d.nospace() << output;
return d;
}
QDebug operator<<(QDebug d, const Scope &scope)
{
QString output;
Overview o;
QTextStream str(&output);
const int size = scope.symbolCount();
str << "Scope of " << size;
if (scope.isNamespaceScope())
str << " namespace";
if (scope.isClassScope())
str << " class";
if (scope.isEnumScope())
str << " enum";
if (scope.isBlockScope())
str << " block";
if (scope.isFunctionScope())
str << " function";
if (scope.isPrototypeScope())
str << " prototype";
if (const Symbol *owner = scope.owner()) {
str << " owner: ";
debugCppSymbolRecursion(str, o, *owner, false, 0);
} else {
str << " 0-owner\n";
}
for (int s = 0; s < size; s++)
debugCppSymbolRecursion(str, o, *scope.symbolAt(s), true, 2);
d.nospace() << output;
return d;
}
} // namespace CPlusPlus
namespace Debugger {
namespace Internal {
@@ -217,6 +293,135 @@ QString stripPointerType(QString type)
return type;
}
/* getUninitializedVariables(): Get variables that are not initialized
* at a certain line of a function from the code model to be able to
* indicate them as not in scope in the locals view.
* Find document + function in the code model, do a double check and
* collect declarative symbols that are in the function past or on
* the current line. blockRecursion() recurses up the scopes
* and collect symbols declared past or on the current line.
* Recursion goes up from the innermost scope, keeping a map
* of occurrences seen, to be able to derive the names of
* shadowed variables as the debugger sees them:
\code
int x; // Occurrence (1), should be reported as "x <shadowed 1>"
if (true) {
int x = 5; (2) // Occurrence (2), should be reported as "x"
}
\endcode
*/
typedef QHash<QString, int> SeenHash;
static void blockRecursion(const CPlusPlus::Overview &overview,
const CPlusPlus::Scope *scope,
unsigned line,
QStringList *uninitializedVariables,
SeenHash *seenHash,
int level = 0)
{
const int size = scope->symbolCount();
for (int s = 0; s < size; s++){
const CPlusPlus::Symbol *symbol = scope->symbolAt(s);
if (symbol->isDeclaration()) {
// Find out about shadowed symbols by bookkeeping
// the already seen occurrences in a hash.
const QString name = overview.prettyName(symbol->name());
SeenHash::iterator it = seenHash->find(name);
if (it == seenHash->end()) {
it = seenHash->insert(name, 0);
} else {
++(it.value());
}
// Is the declaration on or past the current line, that is,
// the variable not initialized.
if (symbol->line() >= line)
uninitializedVariables->push_back(WatchData::shadowedName(name, it.value()));
}
}
// Next block scope.
if (const CPlusPlus::Scope *enclosingScope = scope->enclosingBlockScope())
blockRecursion(overview, enclosingScope, line, uninitializedVariables, seenHash, level + 1);
}
// Inline helper with integer error return codes.
static inline
int getUninitializedVariablesI(const CPlusPlus::Snapshot &snapshot,
const QString &functionName,
const QString &file,
int line,
QStringList *uninitializedVariables)
{
uninitializedVariables->clear();
// Find document
if (snapshot.empty() || functionName.isEmpty() || file.isEmpty() || line < 1)
return 1;
const CPlusPlus::Snapshot::ConstIterator docIt = snapshot.constFind(file);
if (docIt == snapshot.constEnd())
return 2;
const CPlusPlus::Document::Ptr doc = docIt.value();
// Look at symbol at line and find its function. Either it is the
// function itself or some expression/variable.
const CPlusPlus::Symbol *symbolAtLine = doc->findSymbolAt(line, 0);
if (!symbolAtLine)
return 4;
// First figure out the function to do a safety name check
// and the innermost scope at cursor position
const CPlusPlus::Function *function = 0;
const CPlusPlus::Scope *innerMostScope = 0;
if (symbolAtLine->isFunction()) {
function = symbolAtLine->asFunction();
if (function->memberCount() == 1) // Skip over function block
if (CPlusPlus::Block *block = function->memberAt(0)->asBlock())
innerMostScope = block->members();
} else {
if (const CPlusPlus::Scope *functionScope = symbolAtLine->enclosingFunctionScope()) {
function = functionScope->owner()->asFunction();
innerMostScope = symbolAtLine->isBlock() ?
symbolAtLine->asBlock()->members() :
symbolAtLine->enclosingBlockScope();
}
}
if (!function || !innerMostScope)
return 7;
// Compare function names with a bit off fuzz,
// skipping modules from a CDB symbol "lib!foo" or namespaces
// that the code model does not show at this point
CPlusPlus::Overview overview;
const QString name = overview.prettyName(function->name());
if (!functionName.endsWith(name))
return 11;
if (functionName.size() > name.size()) {
const char previousChar = functionName.at(functionName.size() - name.size() - 1).toLatin1();
if (previousChar != ':' && previousChar != '!' )
return 11;
}
// Starting from the innermost block scope, collect declarations.
SeenHash seenHash;
blockRecursion(overview, innerMostScope, line, uninitializedVariables, &seenHash);
return 0;
}
bool getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
const QString &function,
const QString &file,
int line,
QStringList *uninitializedVariables)
{
const int rc = getUninitializedVariablesI(snapshot, function, file, line, uninitializedVariables);
if (debug) {
QString msg;
QTextStream str(&msg);
str << "getUninitializedVariables() " << function << ' ' << file << ':' << line
<< " returns (int) " << rc << " '"
<< uninitializedVariables->join(QString(QLatin1Char(','))) << '\'';
if (rc)
str << " of " << snapshot.keys().size() << " documents";
qDebug() << msg;
}
return rc == 0;
}
QString gdbQuoteTypes(const QString &type)
{
// gdb does not understand sizeof(Core::IFile*).

View File

@@ -45,6 +45,10 @@ namespace Core {
class IEditor;
}
namespace CPlusPlus {
class Snapshot;
}
namespace Debugger {
namespace Internal {
@@ -89,6 +93,15 @@ QString cppExpressionAt(TextEditor::ITextEditor *editor, int pos,
// Decode string data as returned by the dumper helpers.
QString decodeData(const QByteArray &baIn, int encoding);
// Get variables that are not initialized at a certain line
// of a function from the code model. Shadowed variables will
// be reported using the debugger naming conventions '<shadowed n>'
bool getUninitializedVariables(const CPlusPlus::Snapshot &snapshot,
const QString &function,
const QString &file,
int line,
QStringList *uninitializedVariables);
/* Attempt to put common code of the dumper handling into a helper
* class.
* "Custom dumper" is a library compiled against the current

View File

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

View File

@@ -670,6 +670,7 @@ void S60DeviceRunControlBase::signsisProcessFinished()
}
m_launcher = new trk::Launcher();
connect(m_launcher, SIGNAL(finished()), this, SLOT(launcherFinished()));
connect(m_launcher, SIGNAL(canNotConnect(QString)), this, SLOT(printConnectFailed(QString)));
connect(m_launcher, SIGNAL(copyingStarted()), this, SLOT(printCopyingNotice()));
connect(m_launcher, SIGNAL(canNotCreateFile(QString,QString)), this, SLOT(printCreateFileFailed(QString,QString)));
connect(m_launcher, SIGNAL(canNotWriteFile(QString,QString)), this, SLOT(printWriteFileFailed(QString,QString)));
@@ -713,6 +714,11 @@ void S60DeviceRunControlBase::printCloseFileFailed(const QString &filename, cons
emit addToOutputWindow(this, msg.arg(filename, errorMessage));
}
void S60DeviceRunControlBase::printConnectFailed(const QString &errorMessage)
{
emit addToOutputWindow(this, tr("Could not connect to App TRK on device: %1. Restarting App TRK might help.").arg(errorMessage));
}
void S60DeviceRunControlBase::printCopyingNotice()
{
emit addToOutputWindow(this, tr("Copying install file..."));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -51,7 +51,7 @@
#include "TranslationUnit.h"
#include "Control.h"
CPLUSPLUS_BEGIN_NAMESPACE
using namespace CPlusPlus;
ASTVisitor::ASTVisitor(Control *control)
: _control(control)
@@ -111,4 +111,4 @@ void ASTVisitor::getTokenStartPosition(unsigned index, unsigned *line, unsigned
void ASTVisitor::getTokenEndPosition(unsigned index, unsigned *line, unsigned *column) const
{ getPosition(tokenAt(index).end(), line, column); }
CPLUSPLUS_END_NAMESPACE

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -57,7 +57,7 @@
#include <map> // ### replace me with LiteralTable
#include <string>
CPLUSPLUS_BEGIN_NAMESPACE
using namespace CPlusPlus;
template <typename _Iterator>
@@ -89,7 +89,7 @@ public:
: control(control),
translationUnit(0),
diagnosticClient(0)
{ }
{}
~Data()
{
@@ -577,10 +577,31 @@ public:
std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations;
std::vector<ObjCMethod *> objcMethods;
// ObjC context keywords:
Identifier *objcGetterId;
Identifier *objcSetterId;
Identifier *objcReadwriteId;
Identifier *objcReadonlyId;
Identifier *objcAssignId;
Identifier *objcRetainId;
Identifier *objcCopyId;
Identifier *objcNonatomicId;
};
Control::Control()
{ d = new Data(this); }
{
d = new Data(this);
d->objcGetterId = findOrInsertIdentifier("getter");
d->objcSetterId = findOrInsertIdentifier("setter");
d->objcReadwriteId = findOrInsertIdentifier("readwrite");
d->objcReadonlyId = findOrInsertIdentifier("readonly");
d->objcAssignId = findOrInsertIdentifier("assign");
d->objcRetainId = findOrInsertIdentifier("retain");
d->objcCopyId = findOrInsertIdentifier("copy");
d->objcNonatomicId = findOrInsertIdentifier("nonatomic");
}
Control::~Control()
{ delete d; }
@@ -766,4 +787,26 @@ ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsig
ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, Name *name)
{ return d->newObjCMethod(sourceLocation, name); }
CPLUSPLUS_END_NAMESPACE
Identifier *Control::objcGetterId() const
{ return d->objcGetterId; }
Identifier *Control::objcSetterId() const
{ return d->objcSetterId; }
Identifier *Control::objcReadwriteId() const
{ return d->objcReadwriteId; }
Identifier *Control::objcReadonlyId() const
{ return d->objcReadonlyId; }
Identifier *Control::objcAssignId() const
{ return d->objcAssignId; }
Identifier *Control::objcRetainId() const
{ return d->objcRetainId; }
Identifier *Control::objcCopyId() const
{ return d->objcCopyId; }
Identifier *Control::objcNonatomicId() const
{ return d->objcNonatomicId; }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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