diff --git a/src/libs/cplusplus/Icons.cpp b/src/libs/cplusplus/Icons.cpp index 8626088052f1cc946600fe327545145a2cc21ff8..5071efde8ab89ea524549645204e6f61787ea7a5 100644 --- a/src/libs/cplusplus/Icons.cpp +++ b/src/libs/cplusplus/Icons.cpp @@ -100,7 +100,7 @@ QIcon Icons::iconForSymbol(const Symbol *symbol) const } } else if (symbol->isEnum()) { return _enumIcon; - } else if (symbol->isClass()) { + } else if (symbol->isClass() || symbol->isForwardClassDeclaration()) { return _classIcon; } else if (symbol->isNamespace()) { return _namespaceIcon; diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp index 0f973753d0b29326d52c866eea639f1e28c3cea1..331471fe3638652f7f9826ff6c9d6d8bd67a19f2 100644 --- a/src/libs/cplusplus/Overview.cpp +++ b/src/libs/cplusplus/Overview.cpp @@ -42,7 +42,8 @@ Overview::Overview() : _markArgument(0), _showArgumentNames(false), _showReturnTypes(false), - _showFunctionSignatures(true) + _showFunctionSignatures(true), + _showFullyQualifiedNames(false) { } Overview::~Overview() @@ -88,6 +89,16 @@ void Overview::setShowFunctionSignatures(bool showFunctionSignatures) _showFunctionSignatures = showFunctionSignatures; } +bool Overview::showFullyQualifiedNames() const +{ + return _showFullyQualifiedNames; +} + +void Overview::setShowFullyQualifiedNamed(bool showFullyQualifiedNames) +{ + _showFullyQualifiedNames = showFullyQualifiedNames; +} + QString Overview::prettyName(Name *name) const { NamePrettyPrinter pp(this); diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h index 6918ee45ff86539b1462b14df89bc2ba2c249ad8..f7076559f2a93fa94a4010e0e53fe2ae0e32fe20 100644 --- a/src/libs/cplusplus/Overview.h +++ b/src/libs/cplusplus/Overview.h @@ -57,6 +57,9 @@ public: bool showFunctionSignatures() const; void setShowFunctionSignatures(bool showFunctionSignatures); + bool showFullyQualifiedNames() const; + void setShowFullyQualifiedNamed(bool showFullyQualifiedNames); + // 1-based // ### rename unsigned markArgument() const; @@ -77,6 +80,7 @@ private: bool _showArgumentNames: 1; bool _showReturnTypes: 1; bool _showFunctionSignatures: 1; + bool _showFullyQualifiedNames: 1; }; } // end of namespace CPlusPlus diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp index 6e46361b7f42a15a1f77ba4fc7e6eea32fcf6f9a..a198844499c6ac820762b7b62871d584dc87508d 100644 --- a/src/libs/cplusplus/TypePrettyPrinter.cpp +++ b/src/libs/cplusplus/TypePrettyPrinter.cpp @@ -37,9 +37,41 @@ #include <CoreTypes.h> #include <Symbols.h> #include <Scope.h> +#include <QStringList> +#include <QtDebug> using namespace CPlusPlus; + +static QString fullyQualifiedName(Symbol *symbol, const Overview *overview) +{ + QStringList nestedNameSpecifier; + + for (Scope *scope = symbol->scope(); scope && scope->enclosingScope(); + scope = scope->enclosingScope()) + { + Symbol *owner = scope->owner(); + + if (! owner) { + qWarning() << "invalid scope."; // ### better message. + continue; + } + + if (! owner->name()) + nestedNameSpecifier.prepend(QLatin1String("<anonymous>")); + + else { + const QString name = overview->prettyName(owner->name()); + + nestedNameSpecifier.prepend(name); + } + } + + nestedNameSpecifier.append(overview->prettyName(symbol->name())); + + return nestedNameSpecifier.join(QLatin1String("::")); +} + TypePrettyPrinter::TypePrettyPrinter(const Overview *overview) : _overview(overview), _name(0) @@ -150,16 +182,26 @@ void TypePrettyPrinter::visit(Namespace *type) applyPtrOperators(); } -void TypePrettyPrinter::visit(Class *type) +void TypePrettyPrinter::visit(Class *classTy) { - _text += overview()->prettyName(type->name()); + if (overview()->showFullyQualifiedNames()) + _text += fullyQualifiedName(classTy, overview()); + + else + _text += overview()->prettyName(classTy->name()); + applyPtrOperators(); } void TypePrettyPrinter::visit(Enum *type) { - _text += overview()->prettyName(type->name()); + if (overview()->showFullyQualifiedNames()) + _text += fullyQualifiedName(type, overview()); + + else + _text += overview()->prettyName(type->name()); + applyPtrOperators(); } @@ -259,11 +301,14 @@ void TypePrettyPrinter::visit(Function *type) if (! _ptrOperators.isEmpty()) { out(QLatin1Char('(')); applyPtrOperators(false); + if (! _name.isEmpty()) { _text += _name; _name.clear(); } + out(QLatin1Char(')')); + } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) { space(); out(_name); diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 6d836388f025220554a703b084b117d52e885ae0..070aec39d62c08420691d34f7ff57953d51c268c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -40,6 +40,7 @@ #include "cmakestep.h" #include "makestep.h" +#include <projectexplorer/projectexplorerconstants.h> #include <cpptools/cppmodelmanagerinterface.h> #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> @@ -103,7 +104,7 @@ void CMakeProject::parseCMakeLists() } else { // TODO hmm? } - if (newToolChain == m_toolChain) { + if (ProjectExplorer::ToolChain::equals(newToolChain, m_toolChain)) { delete newToolChain; newToolChain = 0; } else { @@ -158,6 +159,21 @@ void CMakeProject::parseCMakeLists() } } +QString CMakeProject::buildParser(const QString &buildConfiguration) const +{ + if (!m_toolChain) + return QString::null; + if (m_toolChain->type() == ProjectExplorer::ToolChain::GCC + || m_toolChain->type() == ProjectExplorer::ToolChain::LinuxICC + || m_toolChain->type() == ProjectExplorer::ToolChain::MinGW) { + return ProjectExplorer::Constants::BUILD_PARSER_GCC; + } else if (m_toolChain->type() == ProjectExplorer::ToolChain::MSVC + || m_toolChain->type() == ProjectExplorer::ToolChain::WINCE) { + return ProjectExplorer::Constants::BUILD_PARSER_MSVC; + } + return QString::null; +} + QStringList CMakeProject::targets() const { QStringList results; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h index 3494441489ef9be686fd14b1a25af23fcd97fb00..4c9b2e1d529c3241f2d2238cf694f3441ed217c7 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.h +++ b/src/plugins/cmakeprojectmanager/cmakeproject.h @@ -105,6 +105,7 @@ public: MakeStep *makeStep() const; CMakeStep *cmakeStep() const; QStringList targets() const; + QString buildParser(const QString &buildConfiguration) const; private: void parseCMakeLists(); diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp index 60f5d04903ebd5398b481d91ef70f5231678b335..44476f6fbe7b2860ae64c70d12bd264dd14e7d40 100644 --- a/src/plugins/cmakeprojectmanager/makestep.cpp +++ b/src/plugins/cmakeprojectmanager/makestep.cpp @@ -34,6 +34,7 @@ #include "makestep.h" #include "cmakeprojectconstants.h" #include "cmakeproject.h" +#include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> #include <QtGui/QFormLayout> @@ -42,6 +43,11 @@ #include <QtGui/QLineEdit> #include <QtGui/QListWidget> +namespace { +bool debug = false; +} + + using namespace CMakeProjectManager; using namespace CMakeProjectManager::Internal; @@ -52,10 +58,42 @@ MakeStep::MakeStep(CMakeProject *pro) MakeStep::~MakeStep() { + delete m_buildParser; + m_buildParser = 0; } bool MakeStep::init(const QString &buildConfiguration) { + // TODO figure out the correct build parser + delete m_buildParser; + m_buildParser = 0; + QString buildParser = m_pro->buildParser(buildConfiguration); + QList<ProjectExplorer::IBuildParserFactory *> buildParserFactories = + ExtensionSystem::PluginManager::instance()->getObjects<ProjectExplorer::IBuildParserFactory>(); + + foreach (ProjectExplorer::IBuildParserFactory * factory, buildParserFactories) + if (factory->canCreate(buildParser)) { + m_buildParser = factory->create(buildParser); + break; + } + if (m_buildParser) { + connect(m_buildParser, SIGNAL(addToOutputWindow(const QString &)), + this, SIGNAL(addToOutputWindow(const QString &)), + Qt::DirectConnection); + connect(m_buildParser, SIGNAL(addToTaskWindow(const QString &, int, int, const QString &)), + this, SLOT(slotAddToTaskWindow(const QString &, int, int, const QString &)), + Qt::DirectConnection); + connect(m_buildParser, SIGNAL(enterDirectory(const QString &)), + this, SLOT(addDirectory(const QString &)), + Qt::DirectConnection); + connect(m_buildParser, SIGNAL(leaveDirectory(const QString &)), + this, SLOT(removeDirectory(const QString &)), + Qt::DirectConnection); + } + + m_openDirectories.clear(); + addDirectory(m_pro->buildDirectory(buildConfiguration)); + setEnabled(buildConfiguration, true); setWorkingDirectory(buildConfiguration, m_pro->buildDirectory(buildConfiguration)); setCommand(buildConfiguration, "make"); // TODO give full path here? @@ -89,6 +127,79 @@ bool MakeStep::immutable() const return true; } +void MakeStep::stdOut(const QString &line) +{ + if (m_buildParser) + m_buildParser->stdOutput(line); + AbstractProcessStep::stdOut(line); +} + +void MakeStep::stdError(const QString &line) +{ + if (m_buildParser) + m_buildParser->stdError(line); + AbstractProcessStep::stdError(line); +} + +void MakeStep::slotAddToTaskWindow(const QString & fn, int type, int linenumber, const QString & description) +{ + QString filePath = fn; + if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) { + // We have no save way to decide which file in which subfolder + // is meant. Therefore we apply following heuristics: + // 1. Search for unique file in directories currently indicated as open by GNU make + // (Enter directory xxx, Leave directory xxx...) + current directory + // 3. Check if file is unique in whole project + // 4. Otherwise give up + + filePath = filePath.trimmed(); + + QList<QFileInfo> possibleFiles; + foreach (const QString &dir, m_openDirectories) { + QFileInfo candidate(dir + QLatin1Char('/') + filePath); + if (debug) + qDebug() << "Checking path " << candidate.filePath(); + if (candidate.exists() + && !possibleFiles.contains(candidate)) { + if (debug) + qDebug() << candidate.filePath() << "exists!"; + possibleFiles << candidate; + } + } + if (possibleFiles.count() == 0) { + if (debug) + qDebug() << "No success. Trying all files in project ..."; + QString fileName = QFileInfo(filePath).fileName(); + foreach (const QString &file, project()->files(ProjectExplorer::Project::AllFiles)) { + QFileInfo candidate(file); + if (candidate.fileName() == fileName) { + if (debug) + qDebug() << "Found " << file; + possibleFiles << candidate; + } + } + } + if (possibleFiles.count() == 1) + filePath = possibleFiles.first().filePath(); + else + qWarning() << "Could not find absolute location of file " << filePath; + } + emit addToTaskWindow(filePath, type, linenumber, description); +} + +void MakeStep::addDirectory(const QString &dir) +{ + if (!m_openDirectories.contains(dir)) + m_openDirectories.insert(dir); +} + +void MakeStep::removeDirectory(const QString &dir) +{ + if (m_openDirectories.contains(dir)) + m_openDirectories.remove(dir); +} + + CMakeProject *MakeStep::project() const { return m_pro; @@ -154,7 +265,6 @@ void MakeBuildStepConfigWidget::init(const QString &buildConfiguration) } // and connect again connect(m_targetsList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*))); - } // diff --git a/src/plugins/cmakeprojectmanager/makestep.h b/src/plugins/cmakeprojectmanager/makestep.h index fbfc007dbe44362154e5ee06e05a41b6115254cc..012fb837bc61fd8f6516374c6510c7cf6376acbb 100644 --- a/src/plugins/cmakeprojectmanager/makestep.h +++ b/src/plugins/cmakeprojectmanager/makestep.h @@ -64,8 +64,17 @@ public: CMakeProject *project() const; bool buildsTarget(const QString &buildConfiguration, const QString &target) const; void setBuildTarget(const QString &buildConfiguration, const QString &target, bool on); +private slots: + void slotAddToTaskWindow(const QString & fn, int type, int linenumber, const QString & description); + void addDirectory(const QString &dir); + void removeDirectory(const QString &dir); +protected: + virtual void stdOut(const QString &line); + virtual void stdError(const QString &line); private: CMakeProject *m_pro; + ProjectExplorer::BuildParserInterface *m_buildParser; + QSet<QString> m_openDirectories; }; class MakeBuildStepConfigWidget :public ProjectExplorer::BuildStepConfigWidget diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index e47fbe658127ab192ef824b1a122007014741627..66dc226e4d7efd0bc33982a8c49f77f1a98db62d 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -47,6 +47,7 @@ #include <CoreTypes.h> #include <FullySpecifiedType.h> #include <Literals.h> +#include <Control.h> #include <Names.h> #include <Scope.h> #include <Symbol.h> @@ -141,30 +142,13 @@ void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint } } -static QString buildHelpId(const FullySpecifiedType &type, - const Symbol *symbol) +static QString buildHelpId(Symbol *symbol, Name *name) { - Name *name = 0; Scope *scope = 0; - if (const Function *f = type->asFunctionType()) { - name = f->name(); - scope = f->scope(); - } else if (const Class *c = type->asClassType()) { - name = c->name(); - scope = c->scope(); - } else if (const Enum *e = type->asEnumType()) { - name = e->name(); - scope = e->scope(); - } else if (const NamedType *t = type->asNamedType()) { - name = t->name(); - } else if (symbol && symbol->isDeclaration()) { - const Declaration *d = symbol->asDeclaration(); - - if (d->scope() && d->scope()->isEnumScope()) { - name = d->name(); - scope = d->scope(); - } + if (symbol) { + scope = symbol->scope(); + name = symbol->name(); } if (! name) @@ -178,14 +162,18 @@ static QString buildHelpId(const FullySpecifiedType &type, qualifiedNames.prepend(overview.prettyName(name)); for (; scope; scope = scope->enclosingScope()) { - if (scope->owner() && scope->owner()->name() && !scope->isEnumScope()) { - Name *name = scope->owner()->name(); + Symbol *owner = scope->owner(); + + if (owner && owner->name() && ! scope->isEnumScope()) { + Name *name = owner->name(); Identifier *id = 0; - if (NameId *nameId = name->asNameId()) { + + if (NameId *nameId = name->asNameId()) id = nameId->identifier(); - } else if (TemplateNameId *nameId = name->asTemplateNameId()) { + + else if (TemplateNameId *nameId = name->asTemplateNameId()) id = nameId->identifier(); - } + if (id) qualifiedNames.prepend(QString::fromLatin1(id->chars(), id->size())); } @@ -194,6 +182,70 @@ static QString buildHelpId(const FullySpecifiedType &type, return qualifiedNames.join(QLatin1String("::")); } +// ### move me +static FullySpecifiedType resolve(const FullySpecifiedType &ty, + const LookupContext &context, + Symbol **resolvedSymbol, + Name **resolvedName) +{ + Control *control = context.control(); + + if (const PointerType *ptrTy = ty->asPointerType()) { + return control->pointerType(resolve(ptrTy->elementType(), context, + resolvedSymbol, resolvedName)); + + } else if (const ReferenceType *refTy = ty->asReferenceType()) { + return control->referenceType(resolve(refTy->elementType(), context, + resolvedSymbol, resolvedName)); + + } else if (const PointerToMemberType *ptrToMemTy = ty->asPointerToMemberType()) { + return control->pointerToMemberType(ptrToMemTy->memberName(), + resolve(ptrToMemTy->elementType(), context, + resolvedSymbol, resolvedName)); + + } else if (const NamedType *namedTy = ty->asNamedType()) { + if (resolvedName) + *resolvedName = namedTy->name(); + + const QList<Symbol *> candidates = context.resolve(namedTy->name()); + + foreach (Symbol *c, candidates) { + if (c->isClass() || c->isEnum()) { + if (resolvedSymbol) + *resolvedSymbol = c; + + return c->type(); + } + } + + } else if (const Namespace *nsTy = ty->asNamespaceType()) { + if (resolvedName) + *resolvedName = nsTy->name(); + + } else if (const Class *classTy = ty->asClassType()) { + if (resolvedName) + *resolvedName = classTy->name(); + + if (resolvedSymbol) + *resolvedSymbol = const_cast<Class *>(classTy); + + } else if (const ForwardClassDeclaration *fwdClassTy = ty->asForwardClassDeclarationType()) { + if (resolvedName) + *resolvedName = fwdClassTy->name(); + + } else if (const Enum *enumTy = ty->asEnumType()) { + if (resolvedName) + *resolvedName = enumTy->name(); + + } else if (const Function *funTy = ty->asFunctionType()) { + if (resolvedName) + *resolvedName = funTy->name(); + + } + + return ty; +} + void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos) { m_helpId.clear(); @@ -262,26 +314,38 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in typeOfExpression(expression, doc, lastSymbol); if (!types.isEmpty()) { - FullySpecifiedType firstType = types.first().first; - Symbol *symbol = types.first().second; - FullySpecifiedType docType = firstType; - - if (const PointerType *pt = firstType->asPointerType()) { - docType = pt->elementType(); - } else if (const ReferenceType *rt = firstType->asReferenceType()) { - docType = rt->elementType(); - } + const TypeOfExpression::Result result = types.first(); - m_helpId = buildHelpId(docType, symbol); - QString displayName = buildHelpId(firstType, symbol); + FullySpecifiedType firstType = result.first; // result of `type of expression'. + Symbol *lookupSymbol = result.second; // lookup symbol - if (!firstType->isClassType() && !firstType->isNamedType()) { - Overview overview; - overview.setShowArgumentNames(true); - overview.setShowReturnTypes(true); - m_toolTip = overview.prettyType(firstType, displayName); - } else { + Symbol *resolvedSymbol = 0; + Name *resolvedName = 0; + firstType = resolve(firstType, typeOfExpression.lookupContext(), + &resolvedSymbol, &resolvedName); + + m_helpId = buildHelpId(resolvedSymbol, resolvedName); + + Symbol *symbol = result.second; + if (resolvedSymbol) + symbol = resolvedSymbol; + + Overview overview; + overview.setShowArgumentNames(true); + overview.setShowReturnTypes(true); + overview.setShowFullyQualifiedNamed(true); + + if (lookupSymbol && lookupSymbol->isDeclaration()) { + Declaration *decl = lookupSymbol->asDeclaration(); + m_toolTip = overview.prettyType(firstType, decl->name()); + + } else if (firstType->isClassType() || firstType->isEnumType() || + firstType->isForwardClassDeclarationType()) { m_toolTip = m_helpId; + + } else { + m_toolTip = overview.prettyType(firstType, m_helpId); + } } } diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 203bfc5b6b9e8b85671520fe615268fc89668633..d0f7141354a7963e0c3e63a0ee36f0328035738f 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -150,10 +150,9 @@ void DebuggerManager::init() { m_status = -1; m_busy = false; - m_shutdown = false; m_attachedPID = 0; - m_startMode = startInternal; + m_startMode = StartInternal; m_disassemblerHandler = 0; m_modulesHandler = 0; @@ -544,6 +543,12 @@ void DebuggerManager::notifyStartupFinished() showStatusMessage(tr("Startup finished. Debugger ready."), -1); } +void DebuggerManager::notifyInferiorStopRequested() +{ + setStatus(DebuggerInferiorStopRequested); + showStatusMessage(tr("Stop requested..."), 5000); +} + void DebuggerManager::notifyInferiorStopped() { resetLocation(); @@ -578,7 +583,7 @@ void DebuggerManager::notifyInferiorExited() void DebuggerManager::notifyInferiorPidChanged(int pid) { //QMessageBox::warning(0, "PID", "PID: " + QString::number(pid)); - qDebug() << "PID: " << pid; + //qDebug() << "PID: " << pid; emit inferiorPidChanged(pid); } @@ -590,9 +595,10 @@ void DebuggerManager::showApplicationOutput(const QString &str) void DebuggerManager::shutdown() { //qDebug() << "DEBUGGER_MANAGER SHUTDOWN START"; - m_shutdown = true; - if (m_engine) + if (m_engine) { + //qDebug() << "SHUTTING DOWN ENGINE" << m_engine; m_engine->shutdown(); + } m_engine = 0; delete scriptEngine; @@ -657,6 +663,12 @@ void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber) { QTC_ASSERT(m_engine, return); QTC_ASSERT(m_breakHandler, return); + if (status() != DebuggerInferiorRunning && status() != DebuggerInferiorStopped) { + showStatusMessage(tr("Changing breakpoint state requires either a " + "fully running or fully stopped application.")); + return; + } + int index = m_breakHandler->indexOf(fileName, lineNumber); if (index == -1) m_breakHandler->setBreakpoint(fileName, lineNumber); @@ -737,13 +749,13 @@ void DebuggerManager::setConfigValue(const QString &name, const QVariant &value) void DebuggerManager::startExternalApplication() { - if (!startNewDebugger(startExternal)) + if (!startNewDebugger(StartExternal)) emit debuggingFinished(); } void DebuggerManager::attachExternalApplication() { - if (!startNewDebugger(attachExternal)) + if (!startNewDebugger(AttachExternal)) emit debuggingFinished(); } @@ -752,7 +764,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) m_startMode = mode; // FIXME: Clean up - if (startMode() == startExternal) { + if (startMode() == StartExternal) { StartExternalDialog dlg(mainWindow()); dlg.setExecutableFile( configValue(QLatin1String("LastExternalExecutableFile")).toString()); @@ -768,7 +780,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) m_processArgs = dlg.executableArguments().split(' '); m_workingDir = QString(); m_attachedPID = -1; - } else if (startMode() == attachExternal) { + } else if (startMode() == AttachExternal) { AttachExternalDialog dlg(mainWindow()); if (dlg.exec() != QDialog::Accepted) return false; @@ -781,7 +793,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) tr("Cannot attach to PID 0")); return false; } - } else if (startMode() == startInternal) { + } else if (startMode() == StartInternal) { if (m_executable.isEmpty()) { QString startDirectory = m_executable; if (m_executable.isEmpty()) { @@ -835,10 +847,9 @@ void DebuggerManager::cleanupViews() void DebuggerManager::exitDebugger() { - if (m_shutdown) - return; - QTC_ASSERT(m_engine, return); - m_engine->exitDebugger(); + //qDebug() << "DebuggerManager::exitDebugger"; + if (m_engine) + m_engine->exitDebugger(); cleanupViews(); setStatus(DebuggerProcessNotReady); setBusyCursor(false); @@ -960,33 +971,6 @@ void DebuggerManager::dumpLog() ts << m_outputWindow->combinedContents(); } -#if 0 -// call after m_gdbProc exited. -void GdbEngine::procFinished() -{ - //qDebug() << "GDB PROCESS FINISHED"; - setStatus(DebuggerProcessNotReady); - showStatusMessage(tr("Done"), 5000); - q->m_breakHandler->procFinished(); - q->m_watchHandler->cleanup(); - m_stackHandler->m_stackFrames.clear(); - m_stackHandler->resetModel(); - m_threadsHandler->resetModel(); - if (q->m_modulesHandler) - q->m_modulesHandler->procFinished(); - q->resetLocation(); - setStatus(DebuggerProcessNotReady); - emit q->previousModeRequested(); - emit q->debuggingFinished(); - //exitDebugger(); - //showStatusMessage("Gdb killed"); - m_shortToFullName.clear(); - m_fullToShortName.clear(); - m_shared = 0; - q->m_busy = false; -} -#endif - void DebuggerManager::addToWatchWindow() { // requires a selection, but that's the only case we want... diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index bd10b7b025967d1793f5145304fd702dcaa0b46f..636187d68cda6491617133e64822f2c6edf6ad09 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -151,6 +151,7 @@ private: // called from the engines after successful startup virtual void notifyStartupFinished() = 0; + virtual void notifyInferiorStopRequested() = 0; virtual void notifyInferiorStopped() = 0; virtual void notifyInferiorUpdateFinished() = 0; virtual void notifyInferiorRunningRequested() = 0; @@ -229,7 +230,7 @@ public: QLabel *statusLabel() const { return m_statusLabel; } DebuggerSettings *settings() { return &m_settings; } - enum StartMode { startInternal, startExternal, attachExternal }; + enum StartMode { StartInternal, StartExternal, AttachExternal }; enum DebuggerType { GdbDebugger, ScriptDebugger, WinDebugger }; public slots: @@ -339,6 +340,7 @@ private: void notifyInferiorStopped(); void notifyInferiorUpdateFinished(); void notifyInferiorRunningRequested(); + void notifyInferiorStopRequested(); void notifyInferiorRunning(); void notifyInferiorExited(); void notifyInferiorPidChanged(int); @@ -466,8 +468,6 @@ private: IDebuggerEngine *engine(); IDebuggerEngine *m_engine; DebuggerSettings m_settings; - // set during application shutdown - bool m_shutdown; }; } // namespace Internal diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index 21313428aefbdc14eca3592321211140176a10b4..149b137727e57a2aa2c1bc2b9a81303d7d94bc3d 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -115,6 +115,8 @@ DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager, connect(m_manager, SIGNAL(inferiorPidChanged(qint64)), this, SLOT(bringApplicationToForeground(qint64)), Qt::QueuedConnection); + connect(this, SIGNAL(stopRequested()), + m_manager, SLOT(exitDebugger())); } void DebuggerRunControl::start() @@ -135,7 +137,7 @@ void DebuggerRunControl::start() //<daniel> andre: + "\qtc-gdbmacros\" //emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable)); - if (m_manager->startNewDebugger(DebuggerManager::startInternal)) + if (m_manager->startNewDebugger(DebuggerManager::StartInternal)) emit started(); else debuggingFinished(); @@ -148,17 +150,21 @@ void DebuggerRunControl::slotAddToOutputWindowInline(const QString &data) void DebuggerRunControl::stop() { - m_manager->exitDebugger(); + //qDebug() << "DebuggerRunControl::stop"; + m_running = false; + emit stopRequested(); } void DebuggerRunControl::debuggingFinished() { m_running = false; + //qDebug() << "DebuggerRunControl::finished"; //emit addToOutputWindow(this, tr("Debugging %1 finished").arg(m_executable)); emit finished(); } bool DebuggerRunControl::isRunning() const { + //qDebug() << "DebuggerRunControl::isRunning" << m_running; return m_running; } diff --git a/src/plugins/debugger/debuggerrunner.h b/src/plugins/debugger/debuggerrunner.h index 0c6d979c0107f89e79ce196beb4511ac5e577abb..7b73178d1031df8a7875ab9f4eba3c56cf47dfed 100644 --- a/src/plugins/debugger/debuggerrunner.h +++ b/src/plugins/debugger/debuggerrunner.h @@ -82,6 +82,9 @@ public: virtual void stop(); virtual bool isRunning() const; +signals: + void stopRequested(); + private slots: void debuggingFinished(); void slotAddToOutputWindowInline(const QString &output); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 0641dac2114aeb7bcf20bb2a35ac90c189adf41f..6b472e25577377bc223d642bcfef0f34303ea381 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -115,6 +115,7 @@ enum GdbCommandType GdbInfoThreads, GdbQueryDataDumper1, GdbQueryDataDumper2, + GdbTemporaryContinue, BreakCondition = 200, BreakEnablePending, @@ -257,6 +258,8 @@ GdbEngine::GdbEngine(DebuggerManager *parent) GdbEngine::~GdbEngine() { + // prevent sending error messages afterwards + m_gdbProc.disconnect(this); } void GdbEngine::initializeConnections() @@ -303,6 +306,7 @@ void GdbEngine::initializeVariables() m_pendingRequests = 0; m_waitingForBreakpointSynchronizationToContinue = false; m_waitingForFirstBreakpointToBeHit = false; + m_commandsToRunOnTemporaryBreak.clear(); } void GdbEngine::gdbProcError(QProcess::ProcessError error) @@ -386,6 +390,11 @@ void GdbEngine::readDebugeeOutput(const QByteArray &data) data.constData(), data.length(), &m_outputCodecState)); } +void GdbEngine::debugMessage(const QString &msg) +{ + emit gdbOutputAvailable("debug:", msg); +} + // called asyncronously as response to Gdb stdout output in // gdbResponseAvailable() void GdbEngine::handleResponse() @@ -643,22 +652,29 @@ void GdbEngine::readGdbStandardOutput() void GdbEngine::interruptInferior() { - if (m_gdbProc.state() == QProcess::NotRunning) + qq->notifyInferiorStopRequested(); + if (m_gdbProc.state() == QProcess::NotRunning) { + debugMessage("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"); + qq->notifyInferiorExited(); return; + } if (q->m_attachedPID > 0) { - if (interruptProcess(q->m_attachedPID)) - qq->notifyInferiorStopped(); + if (!interruptProcess(q->m_attachedPID)) + // qq->notifyInferiorStopped(); + //else + debugMessage(QString("CANNOT INTERRUPT %1").arg(q->m_attachedPID)); return; } #ifdef Q_OS_MAC sendCommand("-exec-interrupt", GdbExecInterrupt); - qq->notifyInferiorStopped(); + //qq->notifyInferiorStopped(); #else - qDebug() << "CANNOT STOP INFERIOR" << m_gdbProc.pid(); - if (interruptChildProcess(m_gdbProc.pid())) - qq->notifyInferiorStopped(); + if (!interruptChildProcess(m_gdbProc.pid())) + // qq->notifyInferiorStopped(); + //else + debugMessage(QString("CANNOT STOP INFERIOR")); #endif } @@ -666,38 +682,30 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) { int pid = pid0.toInt(); if (pid == 0) { - qDebug() << "Cannot parse PID from " << pid0; + debugMessage(QString("Cannot parse PID from %1").arg(pid0)); return; } if (pid == q->m_attachedPID) return; - qDebug() << "FOUND PID " << pid; + debugMessage(QString("FOUND PID %1").arg(pid)); q->m_attachedPID = pid; qq->notifyInferiorPidChanged(pid); } void GdbEngine::sendSynchronizedCommand(const QString & command, - int type, const QVariant &cookie, bool needStop) + int type, const QVariant &cookie, StopNeeded needStop) { - sendCommand(command, type, cookie, needStop, true); + sendCommand(command, type, cookie, needStop, Synchronized); } void GdbEngine::sendCommand(const QString &command, int type, - const QVariant &cookie, bool needStop, bool synchronized) + const QVariant &cookie, StopNeeded needStop, Synchronization synchronized) { if (m_gdbProc.state() == QProcess::NotRunning) { - //qDebug() << "NO GDB PROCESS RUNNING, CMD IGNORED:" << command; + debugMessage("NO GDB PROCESS RUNNING, CMD IGNORED: " + command); return; } - bool temporarilyStopped = false; - if (needStop && q->status() == DebuggerInferiorRunning) { - q->showStatusMessage(tr("Temporarily stopped")); - interruptInferior(); - temporarilyStopped = true; - } - - ++currentToken(); if (synchronized) { ++m_pendingRequests; PENDING_DEBUG(" TYPE " << type << " INCREMENTS PENDING TO: " @@ -710,28 +718,30 @@ void GdbEngine::sendCommand(const QString &command, int type, GdbCookie cmd; cmd.synchronized = synchronized; cmd.command = command; - cmd.command = QString::number(currentToken()) + cmd.command; - if (cmd.command.contains("%1")) - cmd.command = cmd.command.arg(currentToken()); cmd.type = type; cmd.cookie = cookie; - m_cookieForToken[currentToken()] = cmd; + if (needStop && q->status() != DebuggerInferiorStopped + && q->status() != DebuggerProcessStartingUp) { + // queue the commands that we cannot send at once + QTC_ASSERT(q->status() == DebuggerInferiorRunning, + qDebug() << "STATUS: " << q->status()); + q->showStatusMessage(tr("Stopping temporarily.")); + debugMessage("QUEUING COMMAND " + cmd.command); + m_commandsToRunOnTemporaryBreak.append(cmd); + interruptInferior(); + } else if (!command.isEmpty()) { + ++currentToken(); + m_cookieForToken[currentToken()] = cmd; + cmd.command = QString::number(currentToken()) + cmd.command; + if (cmd.command.contains("%1")) + cmd.command = cmd.command.arg(currentToken()); - //qDebug() << ""; - if (!command.isEmpty()) { - //qDebug() << qPrintable(currentTime()) << "RUNNING" << cmd.command; m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); //emit gdbInputAvailable(QString(), " " + currentTime()); //emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command); emit gdbInputAvailable(QString(), cmd.command); } - - if (temporarilyStopped) - sendCommand("-exec-continue"); - - // slows down - //qApp->processEvents(); } void GdbEngine::handleResultRecord(const GdbResultRecord &record) @@ -817,6 +827,7 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, //handleExecRunToFunction(record); break; case GdbExecInterrupt: + qq->notifyInferiorStopped(); break; case GdbExecJumpToLine: handleExecJumpToLine(record); @@ -839,6 +850,10 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, case GdbQueryDataDumper2: handleQueryDataDumper2(record); break; + case GdbTemporaryContinue: + continueInferior(); + q->showStatusMessage(tr("Continuing after temporary stop.")); + break; case BreakList: handleBreakList(record); @@ -920,8 +935,8 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type, break; default: - qDebug() << "FIXME: GdbEngine::handleResult: " - "should not happen" << type; + debugMessage(QString("FIXME: GdbEngine::handleResult: " + "should not happen %1").arg(type)); break; } } @@ -930,7 +945,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command) { //createGdbProcessIfNeeded(); if (m_gdbProc.state() == QProcess::NotRunning) { - qDebug() << "NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: " << command; + debugMessage("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: " + command); return; } @@ -938,11 +953,6 @@ void GdbEngine::executeDebuggerCommand(const QString &command) cmd.command = command; cmd.type = -1; - //m_cookieForToken[currentToken()] = cmd; - //++currentToken(); - - //qDebug() << ""; - //qDebug() << currentTime() << "Running command: " << cmd.command; emit gdbInputAvailable(QString(), cmd.command); m_gdbProc.write(cmd.command.toLatin1() + "\r\n"); } @@ -969,7 +979,7 @@ void GdbEngine::handleQueryPwd(const GdbResultRecord &record) m_pwd = record.data.findChild("consolestreamoutput").data(); m_pwd = m_pwd.trimmed(); #endif - //qDebug() << "PWD RESULT:" << m_pwd; + debugMessage("PWD RESULT: " + m_pwd); } } @@ -1104,6 +1114,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) //MAC: bool isFirstStop = data.findChild("bkptno").data() == "1"; //!MAC: startSymbolName == data.findChild("frame").findChild("func") if (m_waitingForFirstBreakpointToBeHit) { + qq->notifyInferiorStopped(); m_waitingForFirstBreakpointToBeHit = false; // // that's the "early stop" @@ -1143,11 +1154,28 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } + if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { + QTC_ASSERT(q->status() == DebuggerInferiorStopRequested, + qDebug() << "STATUS: " << q->status()) + qq->notifyInferiorStopped(); + q->showStatusMessage(tr("Temporarily stopped.")); + // FIXME: racy + foreach (const GdbCookie &cmd, m_commandsToRunOnTemporaryBreak) { + debugMessage(QString("RUNNING QUEUED COMMAND %1 %2") + .arg(cmd.command).arg(cmd.type)); + sendCommand(cmd.command, cmd.type, cmd.cookie); + } + sendCommand("p temporaryStop", GdbTemporaryContinue); + m_commandsToRunOnTemporaryBreak.clear(); + q->showStatusMessage(tr("Handling queued commands.")); + return; + } + QString msg = data.findChild("consolestreamoutput").data(); if (msg.contains("Stopped due to shared library event") || reason.isEmpty()) { if (qq->wantsSelectedPluginBreakpoints()) { - qDebug() << "SHARED LIBRARY EVENT " << data.toString(); - qDebug() << "PATTERN" << qq->selectedPluginBreakpointsPattern(); + debugMessage("SHARED LIBRARY EVENT: " + data.toString()); + debugMessage("PATTERN: " + qq->selectedPluginBreakpointsPattern()); sendCommand("sharedlibrary " + qq->selectedPluginBreakpointsPattern()); continueInferior(); q->showStatusMessage(tr("Loading %1...").arg(QString(data.toString()))); @@ -1182,6 +1210,8 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) + data.findChild("signal-name").toString(); } q->showStatusMessage(msg); + // FIXME: shouldn't this use a statis change? + debugMessage("CALLING PARENT EXITDEBUGGER"); q->exitDebugger(); return; } @@ -1193,21 +1223,21 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (qq->skipKnownFrames()) { if (reason == "end-stepping-range" || reason == "function-finished") { GdbMi frame = data.findChild("frame"); - //qDebug() << frame.toString(); + //debugMessage(frame.toString()); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; QString funcName = frame.findChild("func").data(); QString fileName = frame.findChild("file").data(); if (isLeavableFunction(funcName, fileName)) { - //qDebug() << "LEAVING" << funcName; + //debugMessage("LEAVING" + funcName); ++stepCounter; q->stepOutExec(); //stepExec(); return; } if (isSkippableFunction(funcName, fileName)) { - //qDebug() << "SKIPPING" << funcName; + //debugMessage("SKIPPING" + funcName); ++stepCounter; q->stepExec(); return; @@ -1227,7 +1257,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) if (reason == "breakpoint-hit") { q->showStatusMessage(tr("Stopped at breakpoint")); GdbMi frame = data.findChild("frame"); - //qDebug() << "HIT BREAKPOINT: " << frame.toString(); + //debugMessage("HIT BREAKPOINT: " + frame.toString()); m_currentFrame = frame.findChild("addr").data() + '%' + frame.findChild("func").data() + '%'; @@ -1243,7 +1273,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data) return; } - qDebug() << "STOPPED FOR UNKNOWN REASON" << data.toString(); + debugMessage("STOPPED FOR UNKNOWN REASON: " + data.toString()); // Ignore it. Will be handled with full response later in the // JumpToLine or RunToFunction handlers #if 1 @@ -1310,7 +1340,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) QString msg = response.data.findChild("consolestreamoutput").data(); QRegExp supported("GNU gdb(.*) (\\d+)\\.(\\d+)(\\.(\\d+))?"); if (supported.indexIn(msg) == -1) { - qDebug() << "UNSUPPORTED GDB VERSION " << msg; + debugMessage("UNSUPPORTED GDB VERSION " + msg); QStringList list = msg.split("\n"); while (list.size() > 2) list.removeLast(); @@ -1331,7 +1361,7 @@ void GdbEngine::handleShowVersion(const GdbResultRecord &response) m_gdbVersion = 10000 * supported.cap(2).toInt() + 100 * supported.cap(3).toInt() + 1 * supported.cap(5).toInt(); - //qDebug() << "GDB VERSION " << m_gdbVersion; + //debugMessage(QString("GDB VERSION: %1").arg(m_gdbVersion)); } } } @@ -1387,7 +1417,7 @@ QString GdbEngine::fullName(const QString &fileName) if (fileName.isEmpty()) return QString(); QString full = m_shortToFullName.value(fileName, QString()); - //qDebug() << "RESOLVING: " << fileName << full; + //debugMessage("RESOLVING: " + fileName + " " + full); if (!full.isEmpty()) return full; QFileInfo fi(fileName); @@ -1397,7 +1427,7 @@ QString GdbEngine::fullName(const QString &fileName) #ifdef Q_OS_WIN full = QDir::cleanPath(full); #endif - //qDebug() << "STORING: " << fileName << full; + //debugMessage("STORING: " + fileName + " " + full); m_shortToFullName[fileName] = full; m_fullToShortName[full] = fileName; return full; @@ -1425,22 +1455,29 @@ void GdbEngine::shutdown() void GdbEngine::exitDebugger() { - //qDebug() << "EXITING: " << m_gdbProc.state(); - if (m_gdbProc.state() == QProcess::Starting) + debugMessage(QString("GDBENGINE EXITDEBUFFER: %1").arg(m_gdbProc.state())); + if (m_gdbProc.state() == QProcess::Starting) { + debugMessage(QString("WAITING FOR GDB STARTUP TO SHUTDOWN: %1") + .arg(m_gdbProc.state())); m_gdbProc.waitForStarted(); + } if (m_gdbProc.state() == QProcess::Running) { + debugMessage(QString("WAITING FOR RUNNING GDB TO SHUTDOWN: %1") + .arg(m_gdbProc.state())); interruptInferior(); sendCommand("kill"); sendCommand("-gdb-exit"); // 20s can easily happen when loading webkit debug information m_gdbProc.waitForFinished(20000); if (m_gdbProc.state() != QProcess::Running) { + debugMessage(QString("FORCING TERMINATION: %1") + .arg(m_gdbProc.state())); m_gdbProc.terminate(); m_gdbProc.waitForFinished(20000); } } if (m_gdbProc.state() != QProcess::NotRunning) - qDebug() << "PROBLEM STOPPING DEBUGGER"; + debugMessage("PROBLEM STOPPING DEBUGGER"); m_outputCollector.shutdown(); initializeVariables(); @@ -1462,7 +1499,7 @@ bool GdbEngine::startDebugger() QString fileName = '"' + fi.absoluteFilePath() + '"'; if (m_gdbProc.state() != QProcess::NotRunning) { - qDebug() << "GDB IS ALREADY RUNNING!"; + debugMessage("GDB IS ALREADY RUNNING!"); return false; } @@ -1525,6 +1562,7 @@ bool GdbEngine::startDebugger() //sendCommand("set pagination off"); sendCommand("set breakpoint pending on", BreakEnablePending); sendCommand("set print elements 10000"); + sendCommand("-data-list-register-names", RegisterListNames); // one of the following is needed to prevent crashes in gdb on code like: // template <class T> T foo() { return T(0); } @@ -1550,6 +1588,8 @@ bool GdbEngine::startDebugger() sendCommand("set unwindonsignal on"); sendCommand("pwd", GdbQueryPwd); + sendCommand("set width 0"); + sendCommand("set height 0"); #ifdef Q_OS_MAC sendCommand("-gdb-set inferior-auto-start-cfm off"); @@ -1579,7 +1619,10 @@ bool GdbEngine::startDebugger() } } - if (q->startMode() == q->startInternal) { + if (q->startMode() == DebuggerManager::AttachExternal) { + sendCommand("attach " + QString::number(q->m_attachedPID)); + } else { + // StartInternal or StartExternal emit gdbInputAvailable(QString(), QString()); sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); //sendCommand("file " + fileName, GdbFileExecAndSymbols); @@ -1593,24 +1636,8 @@ bool GdbEngine::startDebugger() sendCommand("x/2i " + startSymbolName(), GdbStart); } - if (q->startMode() == q->attachExternal) { - sendCommand("attach " + QString::number(q->m_attachedPID)); - } - - if (q->startMode() == q->startExternal) { - //sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); - sendCommand("file " + fileName, GdbFileExecAndSymbols); - #ifdef Q_OS_MAC - sendCommand("sharedlibrary apply-load-rules all"); - #endif - //sendCommand("-file-list-exec-source-files", GdbQuerySources); - //sendCommand("-gdb-set stop-on-solib-events 1"); - } - - sendCommand("-data-list-register-names", RegisterListNames); - // set all to "pending" - if (q->startMode() == q->attachExternal) + if (q->startMode() == DebuggerManager::AttachExternal) qq->breakHandler()->removeAllBreakpoints(); else qq->breakHandler()->setAllPending(); @@ -1622,8 +1649,8 @@ void GdbEngine::continueInferior() { q->resetLocation(); setTokenBarrier(); - qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); + qq->notifyInferiorRunningRequested(); sendCommand("-exec-continue", GdbExecContinue); } @@ -1636,24 +1663,24 @@ void GdbEngine::handleStart(const GdbResultRecord &response) QString msg = response.data.findChild("consolestreamoutput").data(); QRegExp needle("0x([0-9a-f]+) <" + startSymbolName() + "\\+.*>:"); if (needle.indexIn(msg) != -1) { - //qDebug() << "STREAM: " << msg << needle.cap(1); + //debugMessage("STREAM: " + msg + " " + needle.cap(1)); sendCommand("tbreak *0x" + needle.cap(1)); m_waitingForFirstBreakpointToBeHit = true; - sendCommand("-exec-run"); qq->notifyInferiorRunningRequested(); + sendCommand("-exec-run"); } else { - qDebug() << "PARSING START ADDRESS FAILED" << msg; + debugMessage("PARSING START ADDRESS FAILED: " + msg); } } else if (response.resultClass == GdbResultError) { - qDebug() << "PARSING START ADDRESS FAILED" << response.toString(); + debugMessage("PARSING START ADDRESS FAILED: " + response.toString()); } } void GdbEngine::stepExec() { setTokenBarrier(); - qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); + qq->notifyInferiorRunningRequested(); sendCommand("-exec-step", GdbExecStep); } @@ -1674,8 +1701,8 @@ void GdbEngine::stepOutExec() void GdbEngine::nextExec() { setTokenBarrier(); - qq->notifyInferiorRunningRequested(); emit gdbInputAvailable(QString(), QString()); + qq->notifyInferiorRunningRequested(); sendCommand("-exec-next", GdbExecNext); } @@ -1740,12 +1767,12 @@ void GdbEngine::setTokenBarrier() void GdbEngine::setDebugDumpers(bool on) { if (on) { - qDebug() << "SWITCHING ON DUMPER DEBUGGING"; + debugMessage("SWITCHING ON DUMPER DEBUGGING"); sendCommand("set unwindonsignal off"); q->breakByFunction("qDumpObjectData440"); //updateLocals(); } else { - qDebug() << "SWITCHING OFF DUMPER DEBUGGING"; + debugMessage("SWITCHING OFF DUMPER DEBUGGING"); sendCommand("set unwindonsignal on"); } } @@ -1868,8 +1895,8 @@ void GdbEngine::sendInsertBreakpoint(int index) // cmd += "-c " + data->condition + " "; cmd += where; #endif - sendCommand(cmd, BreakInsert, index, true); - //processQueueAndContinue(); + debugMessage(QString("Current state: %1").arg(q->status())); + sendCommand(cmd, BreakInsert, index, NeedsStop); } void GdbEngine::handleBreakList(const GdbResultRecord &record) @@ -2106,10 +2133,11 @@ void GdbEngine::attemptBreakpointSynchronization() foreach (BreakpointData *data, handler->takeRemovedBreakpoints()) { QString bpNumber = data->bpNumber; + debugMessage(QString("DELETING BP %1 IN %2").arg(bpNumber) + .arg(data->markerFileName)); if (!bpNumber.trimmed().isEmpty()) - sendCommand("-break-delete " + bpNumber, BreakDelete, 0, true); - //else - // qDebug() << "BP HAS NO NUMBER: " << data->markerFileName; + sendCommand("-break-delete " + bpNumber, BreakDelete, QVariant(), + NeedsStop); delete data; } diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 0d710e359cf7139c7f45e3d98448a7fa9090d8c9..0b59af8b1c76398dd3835a30645ac5d4a1591ef6 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -158,12 +158,15 @@ private: // queue". resultNeeded == true increments m_pendingResults on // send and decrements on receipt, effectively preventing // watch model updates before everything is finished. - void sendCommand(const QString & command, + enum StopNeeded { DoesNotNeedStop, NeedsStop }; + enum Synchronization { NotSynchronized, Synchronized }; + void sendCommand(const QString &command, int type = 0, const QVariant &cookie = QVariant(), - bool needStop = false, bool synchronized = false); + StopNeeded needStop = DoesNotNeedStop, + Synchronization synchronized = NotSynchronized); void sendSynchronizedCommand(const QString & command, int type = 0, const QVariant &cookie = QVariant(), - bool needStop = false); + StopNeeded needStop = DoesNotNeedStop); void setTokenBarrier(); @@ -193,6 +196,7 @@ private: void handleShowVersion(const GdbResultRecord &response); void handleQueryPwd(const GdbResultRecord &response); void handleQuerySources(const GdbResultRecord &response); + void debugMessage(const QString &msg); OutputCollector m_outputCollector; QTextCodec *m_outputCodec; @@ -334,6 +338,8 @@ private: bool m_waitingForFirstBreakpointToBeHit; bool m_modulesListOutdated; + QList<GdbCookie> m_commandsToRunOnTemporaryBreak; + DebuggerManager *q; IDebuggerManagerAccessForEngines *qq; }; diff --git a/src/plugins/qt4projectmanager/buildparserfactory.cpp b/src/plugins/projectexplorer/buildparserfactory.cpp similarity index 95% rename from src/plugins/qt4projectmanager/buildparserfactory.cpp rename to src/plugins/projectexplorer/buildparserfactory.cpp index 9b52fafb23be7c833addd046bd9309b9a1175882..2cad67e2145ec98f48f1e716d026a6122dd8a245 100644 --- a/src/plugins/qt4projectmanager/buildparserfactory.cpp +++ b/src/plugins/projectexplorer/buildparserfactory.cpp @@ -33,11 +33,11 @@ #include "buildparserfactory.h" -#include "qt4projectmanagerconstants.h" +#include "projectexplorerconstants.h" #include "gccparser.h" #include "msvcparser.h" -using namespace Qt4ProjectManager::Internal; +using namespace ProjectExplorer::Internal; GccParserFactory::~GccParserFactory() { diff --git a/src/plugins/qt4projectmanager/buildparserfactory.h b/src/plugins/projectexplorer/buildparserfactory.h similarity index 94% rename from src/plugins/qt4projectmanager/buildparserfactory.h rename to src/plugins/projectexplorer/buildparserfactory.h index a52c33f719323800d01e77cc7a47d694ca220e75..98690d250764fdf76bd81f4dc75893ab8cc4bb00 100644 --- a/src/plugins/qt4projectmanager/buildparserfactory.h +++ b/src/plugins/projectexplorer/buildparserfactory.h @@ -36,14 +36,14 @@ #include <projectexplorer/buildparserinterface.h> -namespace Qt4ProjectManager { +namespace ProjectExplorer { namespace Internal { class GccParserFactory : public ProjectExplorer::IBuildParserFactory { Q_OBJECT public: - GccParserFactory() {}; + GccParserFactory() {} virtual ~GccParserFactory(); virtual bool canCreate(const QString & name) const; virtual ProjectExplorer::BuildParserInterface * create(const QString & name) const; @@ -53,13 +53,13 @@ class MsvcParserFactory : public ProjectExplorer::IBuildParserFactory { Q_OBJECT public: - MsvcParserFactory() {}; + MsvcParserFactory() {} virtual ~MsvcParserFactory(); virtual bool canCreate(const QString & name) const; virtual ProjectExplorer::BuildParserInterface * create(const QString & name) const; }; } // namespace Internal -} // namespace Qt4ProjectManager +} // namespace ProjectExplorer #endif // BUILDPARSERFACTORY_H diff --git a/src/plugins/qt4projectmanager/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp similarity index 96% rename from src/plugins/qt4projectmanager/gccparser.cpp rename to src/plugins/projectexplorer/gccparser.cpp index b71a3362f55f12a07c4b559c7d66868542b47caf..97a358a0e4ccbc6ac396602e0dee5c014cd360be 100644 --- a/src/plugins/qt4projectmanager/gccparser.cpp +++ b/src/plugins/projectexplorer/gccparser.cpp @@ -32,11 +32,11 @@ ***************************************************************************/ #include "gccparser.h" -#include "qt4projectmanagerconstants.h" +#include "projectexplorerconstants.h" #include <QDebug> -using namespace Qt4ProjectManager; +using namespace ProjectExplorer; GccParser::GccParser() { @@ -56,7 +56,7 @@ GccParser::GccParser() QString GccParser::name() const { - return QLatin1String(Qt4ProjectManager::Constants::BUILD_PARSER_GCC); + return QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_GCC); } void GccParser::stdOutput(const QString & line) diff --git a/src/plugins/qt4projectmanager/gccparser.h b/src/plugins/projectexplorer/gccparser.h similarity index 95% rename from src/plugins/qt4projectmanager/gccparser.h rename to src/plugins/projectexplorer/gccparser.h index 80796f4be2a11b2348b9893e3b81064ef33a3dd7..47e4aae4e136bd29f7ad0114915648f24408683a 100644 --- a/src/plugins/qt4projectmanager/gccparser.h +++ b/src/plugins/projectexplorer/gccparser.h @@ -34,11 +34,11 @@ #ifndef GCCPARSER_H #define GCCPARSER_H -#include <projectexplorer/buildparserinterface.h> +#include "buildparserinterface.h" #include <QtCore/QRegExp> -namespace Qt4ProjectManager { +namespace ProjectExplorer { class GccParser : public ProjectExplorer::BuildParserInterface { diff --git a/src/plugins/qt4projectmanager/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp similarity index 95% rename from src/plugins/qt4projectmanager/msvcparser.cpp rename to src/plugins/projectexplorer/msvcparser.cpp index d4a23264c79c2782f2f71bd3e4c19ffaee25cd87..b089638dd1a218c05e59864105ee1dddc5d86634 100644 --- a/src/plugins/qt4projectmanager/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -32,11 +32,11 @@ ***************************************************************************/ #include "msvcparser.h" -#include "qt4projectmanagerconstants.h" +#include "projectexplorerconstants.h" #include <QtCore/QStringList> -using namespace Qt4ProjectManager; +using namespace ProjectExplorer; MsvcParser::MsvcParser() { @@ -48,7 +48,7 @@ MsvcParser::MsvcParser() QString MsvcParser::name() const { - return QLatin1String(Qt4ProjectManager::Constants::BUILD_PARSER_MSVC); + return QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_MSVC); } void MsvcParser::stdError(const QString & line) diff --git a/src/plugins/qt4projectmanager/msvcparser.h b/src/plugins/projectexplorer/msvcparser.h similarity index 95% rename from src/plugins/qt4projectmanager/msvcparser.h rename to src/plugins/projectexplorer/msvcparser.h index 06e0c3e6d612497e803c70ad15f6327642532d5e..29587cadb6772e0d77e8d45b74ccafb2e92a7e5a 100644 --- a/src/plugins/qt4projectmanager/msvcparser.h +++ b/src/plugins/projectexplorer/msvcparser.h @@ -34,11 +34,11 @@ #ifndef MSVCPARSER_H #define MSVCPARSER_H -#include <projectexplorer/buildparserinterface.h> +#include "buildparserinterface.h" #include <QtCore/QRegExp> -namespace Qt4ProjectManager { +namespace ProjectExplorer { class MsvcParser : public ProjectExplorer::BuildParserInterface { diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 2380c9b61d644090d9dcb767e8f36ff8ae40a079..c4a94042df5363d56f209239ac2c9e06537cbb0e 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -59,6 +59,7 @@ #include "scriptwrappers.h" #include "session.h" #include "sessiondialog.h" +#include "buildparserfactory.h" #include <coreplugin/basemode.h> #include <coreplugin/coreconstants.h> @@ -233,6 +234,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new ProjectFileWizardExtension); + // Build parsers + addAutoReleasedObject(new GccParserFactory); + addAutoReleasedObject(new MsvcParserFactory); + // context menus Core::ActionContainer *msessionContextMenu = am->createMenu(Constants::M_SESSIONCONTEXT); diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 2cfeecf47cfaac320856662220deeac7f576c998..1feeea4ebd87c6145a9c80537baa526ca7e075c9 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -54,7 +54,10 @@ HEADERS += projectexplorer.h \ projectmodels.h \ currentprojectfind.h \ toolchain.h \ - cesdkhandler.h + cesdkhandler.h\ + buildparserfactory.h\ + gccparser.h\ + msvcparser.h SOURCES += projectexplorer.cpp \ projectwindow.cpp \ buildmanager.cpp \ @@ -97,7 +100,10 @@ SOURCES += projectexplorer.cpp \ projectmodels.cpp \ currentprojectfind.cpp \ toolchain.cpp \ - cesdkhandler.cpp + cesdkhandler.cpp\ + buildparserfactory.cpp \ + gccparser.cpp\ + msvcparser.cpp FORMS += dependenciespanel.ui \ buildsettingspropertiespage.ui \ processstep.ui \ diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index e65ca54d099524d1f114829786d46f61f58a523b..183259be10d15d035a4b7e97dcc9642322b1961f 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -176,6 +176,11 @@ const char * const CPP_HEADER_MIMETYPE = "text/x-c++hdr"; const char * const FORM_MIMETYPE = "application/x-designer"; const char * const RESOURCE_MIMETYPE = "application/vnd.nokia.xml.qt.resource"; +// build parsers +const char * const BUILD_PARSER_MSVC = "BuildParser.MSVC"; +const char * const BUILD_PARSER_GCC = "BuildParser.Gcc"; + + } // namespace Constants } // namespace ProjectExplorer diff --git a/src/plugins/qt4projectmanager/makestep.cpp b/src/plugins/qt4projectmanager/makestep.cpp index 8e6eb1542d62a6420d2c59e6fa73ef8651508f9b..46683252d0bd420ce149adde9c1427c0fdfbc883 100644 --- a/src/plugins/qt4projectmanager/makestep.cpp +++ b/src/plugins/qt4projectmanager/makestep.cpp @@ -36,6 +36,8 @@ #include "qt4project.h" #include "qt4projectmanagerconstants.h" +#include <projectexplorer/projectexplorerconstants.h> + #include <extensionsystem/pluginmanager.h> #include <utils/qtcassert.h> @@ -71,9 +73,9 @@ ProjectExplorer::BuildParserInterface *MakeStep::buildParser(const QtVersion * c QString buildParser; ProjectExplorer::ToolChain::ToolChainType type = version->toolchainType(); if ( type == ProjectExplorer::ToolChain::MSVC || type == ProjectExplorer::ToolChain::WINCE) - buildParser = Constants::BUILD_PARSER_MSVC; + buildParser = ProjectExplorer::Constants::BUILD_PARSER_MSVC; else - buildParser = Constants::BUILD_PARSER_GCC; + buildParser = ProjectExplorer::Constants::BUILD_PARSER_GCC; QList<IBuildParserFactory *> buildParserFactories = ExtensionSystem::PluginManager::instance()->getObjects<ProjectExplorer::IBuildParserFactory>(); diff --git a/src/plugins/qt4projectmanager/qt4projectmanager.pro b/src/plugins/qt4projectmanager/qt4projectmanager.pro index 5e18e1f9d483f888d5287af1446be66f8409777e..04ac5d8067be1459f3427055fda69ed6bf792b4c 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanager.pro +++ b/src/plugins/qt4projectmanager/qt4projectmanager.pro @@ -28,9 +28,6 @@ HEADERS = qt4projectmanagerplugin.h \ makestep.h \ qmakestep.h \ qmakebuildstepfactory.h \ - gccparser.h \ - msvcparser.h \ - buildparserfactory.h \ deployhelper.h \ embeddedpropertiespage.h \ qt4runconfiguration.h \ @@ -63,9 +60,6 @@ SOURCES = qt4projectmanagerplugin.cpp \ makestep.cpp \ qmakestep.cpp \ qmakebuildstepfactory.cpp \ - gccparser.cpp \ - msvcparser.cpp \ - buildparserfactory.cpp \ deployhelper.cpp \ embeddedpropertiespage.cpp \ qt4runconfiguration.cpp \ diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h index 1ef68a68f5f89bb9301c982360fb983ed6e0ccb8..7261310ff5fbc3a9471cb190b120b29f1ae01968 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h +++ b/src/plugins/qt4projectmanager/qt4projectmanagerconstants.h @@ -79,10 +79,6 @@ const char * const GDBMACROSBUILDSTEP = "trolltech.qt4projectmanager.gdbmaros"; const char * const QT4RUNSTEP = "trolltech.qt4projectmanager.qt4runstep"; const char * const DEPLOYHELPERRUNSTEP = "trolltech.qt4projectmanager.deployhelperrunstep"; -// build parsers -const char * const BUILD_PARSER_MSVC = "BuildParser.MSVC"; -const char * const BUILD_PARSER_GCC = "BuildParser.Gcc"; - // views const char * const VIEW_DETAILED = "Qt4.View.Detailed"; const char * const VIEW_PROFILESONLY = "Qt4.View.ProjectHierarchy"; diff --git a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp index 0d90983aa88f389999da2c8a909283490364ec23..f1df421b6263c8b27971b3577c2115b8598c0e12 100644 --- a/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp +++ b/src/plugins/qt4projectmanager/qt4projectmanagerplugin.cpp @@ -41,7 +41,6 @@ #include "qt4projectmanagerconstants.h" #include "qt4project.h" #include "qmakebuildstepfactory.h" -#include "buildparserfactory.h" #include "qtversionmanager.h" #include "embeddedpropertiespage.h" #include "qt4runconfiguration.h" @@ -133,9 +132,6 @@ bool Qt4ProjectManagerPlugin::initialize(const QStringList &arguments, QString * addAutoReleasedObject(new MakeBuildStepFactory); addAutoReleasedObject(new GdbMacrosBuildStepFactory); - addAutoReleasedObject(new GccParserFactory); - addAutoReleasedObject(new MsvcParserFactory); - m_qtVersionManager = new QtVersionManager; addObject(m_qtVersionManager); diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 8a9c201dc5d1be492b55da70e59f949fb0145df7..6ab5c9b92ec048f91e18340b753a05a083ffe101 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -1178,7 +1178,7 @@ unsigned DeclaratorListAST::lastToken() const { for (const DeclaratorListAST *it = this; it; it = it->next) { if (! it->next) - return it->lastToken(); + return it->declarator->lastToken(); } return 0; } diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index 2909c0775ab2a90b3bd105214175c9acf664ae38..3233c7449f1b4c7059f81e876e4f463bf6f8db61 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -132,6 +132,7 @@ class BaseClass; class Block; class Class; class Enum; +class ForwardClassDeclaration; class Use; diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index ee9e80ffa66a2e59b76c0713d3ab9f6365a16e22..f8ddde8b48e8b8162ba29888fafd067633dbcf79 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -136,6 +136,23 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) } } + if (! ast->declarators && ast->decl_specifier_seq && ! ast->decl_specifier_seq->next) { + if (ElaboratedTypeSpecifierAST *elab_type_spec = ast->decl_specifier_seq->asElaboratedTypeSpecifier()) { + Name *name = semantic()->check(elab_type_spec->name, _scope); + ForwardClassDeclaration *symbol = + control()->newForwardClassDeclaration(elab_type_spec->firstToken(), + name); + + if (_templateParameters) { + symbol->setTemplateParameters(_templateParameters); + _templateParameters = 0; + } + + _scope->enterSymbol(symbol); + return false; + } + } + List<Declaration *> **decl_it = &ast->symbols; for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { Name *name = 0; diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp index 4d708f4340c5553206984ba155ea2222bd53c500..7f5fd273caeb8027b7d4848d2dabb6a67254431a 100644 --- a/src/shared/cplusplus/Control.cpp +++ b/src/shared/cplusplus/Control.cpp @@ -124,6 +124,7 @@ public: delete_array_entries(usingNamespaceDirectives); delete_array_entries(enums); delete_array_entries(usingDeclarations); + delete_array_entries(classForwardDeclarations); } NameId *findOrInsertNameId(Identifier *id) @@ -322,6 +323,14 @@ public: return u; } + ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name) + { + ForwardClassDeclaration *c = new ForwardClassDeclaration(translationUnit, + sourceLocation, name); + classForwardDeclarations.push_back(c); + return c; + } + Enum *newEnum(unsigned sourceLocation, Name *name) { Enum *e = new Enum(translationUnit, @@ -477,6 +486,7 @@ public: std::vector<UsingNamespaceDirective *> usingNamespaceDirectives; std::vector<Enum *> enums; std::vector<UsingDeclaration *> usingDeclarations; + std::vector<ForwardClassDeclaration *> classForwardDeclarations; }; Control::Control() @@ -632,4 +642,9 @@ UsingNamespaceDirective *Control::newUsingNamespaceDirective(unsigned sourceLoca UsingDeclaration *Control::newUsingDeclaration(unsigned sourceLocation, Name *name) { return d->newUsingDeclaration(sourceLocation, name); } +ForwardClassDeclaration *Control::newForwardClassDeclaration(unsigned sourceLocation, + Name *name) +{ return d->newForwardClassDeclaration(sourceLocation, name); } + + CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h index 98c1bacdd29079061706c2a8f75859db52164d15..cb64a888aac739a5cb2b63d71f4207b3b58545a2 100644 --- a/src/shared/cplusplus/Control.h +++ b/src/shared/cplusplus/Control.h @@ -148,6 +148,9 @@ public: /// Creates a new UsingDeclaration symbol. UsingDeclaration *newUsingDeclaration(unsigned sourceLocation, Name *name = 0); + /// Creates a new ForwardClassDeclaration symbol. + ForwardClassDeclaration *newForwardClassDeclaration(unsigned sourceLocation, Name *name = 0); + Identifier *findOrInsertIdentifier(const char *chars, unsigned size); Identifier *findOrInsertIdentifier(const char *chars); diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp index 8e9ba22bb78f5c034c054c69cb3eede9837e76f1..6effeaa1c7d858d67339c858a6c612efb0348449 100644 --- a/src/shared/cplusplus/Symbol.cpp +++ b/src/shared/cplusplus/Symbol.cpp @@ -334,6 +334,9 @@ bool Symbol::isNamespace() const bool Symbol::isClass() const { return asClass() != 0; } +bool Symbol::isForwardClassDeclaration() const +{ return asForwardClassDeclaration() != 0; } + bool Symbol::isBlock() const { return asBlock() != 0; } diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h index 2b9a428dce9bcad49254692afad2e7cb4cafb0cc..318cc1ca83b2c14f91ca1ea9d1cffe7938430ff3 100644 --- a/src/shared/cplusplus/Symbol.h +++ b/src/shared/cplusplus/Symbol.h @@ -197,6 +197,9 @@ public: /// Returns true if this Symbol is a BaseClass. bool isBaseClass() const; + /// Returns true if this Symbol is a ForwardClassDeclaration. + bool isForwardClassDeclaration() const; + virtual const ScopedSymbol *asScopedSymbol() const { return 0; } virtual const Enum *asEnum() const { return 0; } virtual const Function *asFunction() const { return 0; } @@ -208,6 +211,7 @@ public: virtual const Declaration *asDeclaration() const { return 0; } virtual const Argument *asArgument() const { return 0; } virtual const BaseClass *asBaseClass() const { return 0; } + virtual const ForwardClassDeclaration *asForwardClassDeclaration() const { return 0; } virtual ScopedSymbol *asScopedSymbol() { return 0; } virtual Enum *asEnum() { return 0; } @@ -220,6 +224,7 @@ public: virtual Declaration *asDeclaration() { return 0; } virtual Argument *asArgument() { return 0; } virtual BaseClass *asBaseClass() { return 0; } + virtual ForwardClassDeclaration *asForwardClassDeclaration() { return 0; } /// Returns this Symbol's type. virtual FullySpecifiedType type() const = 0; diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h index f0f4738de7f571ed06454aafa95492a069789914..b7113715858d91be43703f4cd3080eef19fabcd5 100644 --- a/src/shared/cplusplus/SymbolVisitor.h +++ b/src/shared/cplusplus/SymbolVisitor.h @@ -82,6 +82,7 @@ public: virtual bool visit(Namespace *) { return true; } virtual bool visit(Class *) { return true; } virtual bool visit(Block *) { return true; } + virtual bool visit(ForwardClassDeclaration *) { return true; } }; CPLUSPLUS_END_NAMESPACE diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp index 6fae11453bf48d61516745528e860f208c50d65c..b8195c7db1861c00730edafd3d24a3f5065e0b5d 100644 --- a/src/shared/cplusplus/Symbols.cpp +++ b/src/shared/cplusplus/Symbols.cpp @@ -401,6 +401,53 @@ void BaseClass::setVirtual(bool isVirtual) void BaseClass::visitSymbol0(SymbolVisitor *visitor) { visitor->visit(this); } +ForwardClassDeclaration::ForwardClassDeclaration(TranslationUnit *translationUnit, + unsigned sourceLocation, Name *name) + : Symbol(translationUnit, sourceLocation, name), + _templateParameters(0) +{ } + +ForwardClassDeclaration::~ForwardClassDeclaration() +{ delete _templateParameters; } + +unsigned ForwardClassDeclaration::templateParameterCount() const +{ + if (! _templateParameters) + return 0; + return _templateParameters->symbolCount(); +} + +Symbol *ForwardClassDeclaration::templateParameterAt(unsigned index) const +{ return _templateParameters->symbolAt(index); } + +Scope *ForwardClassDeclaration::templateParameters() const +{ return _templateParameters; } + +void ForwardClassDeclaration::setTemplateParameters(Scope *templateParameters) +{ _templateParameters = templateParameters; } + +FullySpecifiedType ForwardClassDeclaration::type() const +{ return FullySpecifiedType(const_cast<ForwardClassDeclaration *>(this)); } + +bool ForwardClassDeclaration::isEqualTo(const Type *other) const +{ + if (const ForwardClassDeclaration *otherClassFwdTy = other->asForwardClassDeclarationType()) { + if (name() == otherClassFwdTy->name()) + return true; + else if (name() && otherClassFwdTy->name()) + return name()->isEqualTo(otherClassFwdTy->name()); + + return false; + } + return false; +} + +void ForwardClassDeclaration::visitSymbol0(SymbolVisitor *visitor) +{ visitor->visit(this); } + +void ForwardClassDeclaration::accept0(TypeVisitor *visitor) +{ visitor->visit(this); } + Class::Class(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name) : ScopedSymbol(translationUnit, sourceLocation, name), _key(ClassKey), diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h index 2153b55393e8e925a29a4393e8deac69e626d718..1253621fec3b60e1f507205b0d231219bda04cef 100644 --- a/src/shared/cplusplus/Symbols.h +++ b/src/shared/cplusplus/Symbols.h @@ -199,6 +199,42 @@ protected: virtual void visitSymbol0(SymbolVisitor *visitor); }; +class CPLUSPLUS_EXPORT ForwardClassDeclaration: public Symbol, public Type +{ +public: + ForwardClassDeclaration(TranslationUnit *translationUnit, unsigned sourceLocation, Name *name); + virtual ~ForwardClassDeclaration(); + + unsigned templateParameterCount() const; + Symbol *templateParameterAt(unsigned index) const; + + Scope *templateParameters() const; + void setTemplateParameters(Scope *templateParameters); + + virtual FullySpecifiedType type() const; + + virtual bool isEqualTo(const Type *other) const; + + virtual const ForwardClassDeclaration *asForwardClassDeclaration() const + { return this; } + + virtual ForwardClassDeclaration *asForwardClassDeclaration() + { return this; } + + virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const + { return this; } + + virtual ForwardClassDeclaration *asForwardClassDeclarationType() + { return this; } + +protected: + virtual void visitSymbol0(SymbolVisitor *visitor); + virtual void accept0(TypeVisitor *visitor); + +private: + Scope *_templateParameters; +}; + class CPLUSPLUS_EXPORT Enum: public ScopedSymbol, public Type { public: @@ -295,7 +331,6 @@ protected: virtual void accept0(TypeVisitor *visitor); private: - Name *_name; Scope *_templateParameters; FullySpecifiedType _returnType; union { diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp index b88b0afab4881efe7ad7f8a185b55b2fb6fd77df..f2128f03e80160c8a3754f5a306ffa5312452172 100644 --- a/src/shared/cplusplus/Type.cpp +++ b/src/shared/cplusplus/Type.cpp @@ -102,6 +102,9 @@ bool Type::isClassType() const bool Type::isEnumType() const { return asEnumType() != 0; } +bool Type::isForwardClassDeclarationType() const +{ return asForwardClassDeclarationType() != 0; } + void Type::accept(TypeVisitor *visitor) { if (visitor->preVisit(this)) diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h index 320555b40cfd96cf0f7a2f47c87a7d97d1f30a8c..1ac54f4dfbe39d4b1566fc41ac207869ac93951e 100644 --- a/src/shared/cplusplus/Type.h +++ b/src/shared/cplusplus/Type.h @@ -80,6 +80,7 @@ public: bool isNamespaceType() const; bool isClassType() const; bool isEnumType() const; + bool isForwardClassDeclarationType() const; virtual const VoidType *asVoidType() const { return 0; } virtual const IntegerType *asIntegerType() const { return 0; } @@ -93,6 +94,7 @@ public: virtual const Namespace *asNamespaceType() const { return 0; } virtual const Class *asClassType() const { return 0; } virtual const Enum *asEnumType() const { return 0; } + virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; } virtual VoidType *asVoidType() { return 0; } virtual IntegerType *asIntegerType() { return 0; } @@ -106,6 +108,7 @@ public: virtual Namespace *asNamespaceType() { return 0; } virtual Class *asClassType() { return 0; } virtual Enum *asEnumType() { return 0; } + virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; } void accept(TypeVisitor *visitor); static void accept(Type *type, TypeVisitor *visitor); diff --git a/src/shared/cplusplus/TypeVisitor.h b/src/shared/cplusplus/TypeVisitor.h index 16fb37c4ad0a5130bd7086ac7f1be159d71e1d6c..41cc57515756dd5bdfdabcd0d43015470d01baf0 100644 --- a/src/shared/cplusplus/TypeVisitor.h +++ b/src/shared/cplusplus/TypeVisitor.h @@ -84,6 +84,7 @@ public: virtual void visit(Namespace *) {} virtual void visit(Class *) {} virtual void visit(Enum *) {} + virtual void visit(ForwardClassDeclaration *) {} }; CPLUSPLUS_END_NAMESPACE