From 7e10664e6adf34a3280eb765feaad5e36213c9d1 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 19 Feb 2009 13:01:01 +0100 Subject: [PATCH 1/6] Instroduced TranslationUnit::spell(tokenIndex). --- src/shared/cplusplus/ASTVisitor.cpp | 7 +------ src/shared/cplusplus/TranslationUnit.cpp | 8 ++++++++ src/shared/cplusplus/TranslationUnit.h | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/shared/cplusplus/ASTVisitor.cpp b/src/shared/cplusplus/ASTVisitor.cpp index 7b9ca1ed7fa..d08d1c4d93d 100644 --- a/src/shared/cplusplus/ASTVisitor.cpp +++ b/src/shared/cplusplus/ASTVisitor.cpp @@ -77,12 +77,7 @@ int ASTVisitor::tokenKind(unsigned index) const { return translationUnit()->tokenKind(index); } const char *ASTVisitor::spell(unsigned index) const -{ - if (! index) - return 0; - - return translationUnit()->tokenAt(index).spell(); -} +{ return translationUnit()->spell(index); } Identifier *ASTVisitor::identifier(unsigned index) const { return translationUnit()->identifier(index); } diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp index 40a95c0f05d..ebadf35c75a 100644 --- a/src/shared/cplusplus/TranslationUnit.cpp +++ b/src/shared/cplusplus/TranslationUnit.cpp @@ -134,6 +134,14 @@ const Token &TranslationUnit::tokenAt(unsigned index) const int TranslationUnit::tokenKind(unsigned index) const { return _tokens->at(index).kind; } +const char *TranslationUnit::spell(unsigned index) const +{ + if (! index) + return 0; + + return _tokens->at(index).spell(); +} + Identifier *TranslationUnit::identifier(unsigned index) const { return _tokens->at(index).identifier; } diff --git a/src/shared/cplusplus/TranslationUnit.h b/src/shared/cplusplus/TranslationUnit.h index aa490701ef9..7a57950ac34 100644 --- a/src/shared/cplusplus/TranslationUnit.h +++ b/src/shared/cplusplus/TranslationUnit.h @@ -87,6 +87,7 @@ public: unsigned tokenCount() const; const Token &tokenAt(unsigned index) const; int tokenKind(unsigned index) const; + const char *spell(unsigned index) const; unsigned matchingBrace(unsigned index) const; Identifier *identifier(unsigned index) const; From 6178a44fc20411235b5403d867e69dfadb2852f5 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 19 Feb 2009 13:52:05 +0100 Subject: [PATCH 2/6] Warning for using-directive in class scope. --- src/shared/cplusplus/CheckDeclaration.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index f8ddde8b48e..038583c27d4 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -389,6 +389,11 @@ bool CheckDeclaration::visit(UsingDirectiveAST *ast) UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(ast->firstToken(), name); ast->symbol = u; _scope->enterSymbol(u); + + if (! (_scope->isBlockScope() || _scope->isNamespaceScope())) + translationUnit()->error(ast->firstToken(), + "using-directive not within namespace or block scope"); + return false; } From 90b094e832125b4ad441f982473c2ff26ac5cac8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Feb 2009 17:47:44 +0100 Subject: [PATCH 3/6] Make the git plugin look for the binary in the path specified in the settings. Previously, the environment was passed to the process, but that did not affect the location of the binary. --- src/libs/utils/synchronousprocess.cpp | 105 ++++++++++++++++++++++++++ src/libs/utils/synchronousprocess.h | 6 ++ src/plugins/git/gitclient.cpp | 13 ++-- src/plugins/git/gitclient.h | 1 + src/plugins/git/gitcommand.cpp | 6 +- src/plugins/git/gitcommand.h | 7 +- src/plugins/git/gitsettings.cpp | 29 +++++++ src/plugins/git/gitsettings.h | 2 + src/plugins/git/settingspage.cpp | 17 ++++- 9 files changed, 173 insertions(+), 13 deletions(-) diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp index 667416a3406..597be2932be 100644 --- a/src/libs/utils/synchronousprocess.cpp +++ b/src/libs/utils/synchronousprocess.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include @@ -366,5 +368,108 @@ void SynchronousProcess::processStdErr(bool emitSignals) } } +// Path utilities + +enum OS_Type { OS_Mac, OS_Windows, OS_Unix }; + +#ifdef Q_OS_WIN +static const OS_Type pathOS = OS_Windows; +#else +# ifdef Q_OS_MAC +static const OS_Type pathOS = OS_Mac; +# else +static const OS_Type pathOS = OS_Unix; +# endif +#endif + +// Locate a binary in a directory, applying all kinds of +// extensions the operating system supports. +static QString checkBinary(const QDir &dir, const QString &binary) +{ + // naive UNIX approach + const QFileInfo info(dir.filePath(binary)); + if (info.isFile() && info.isExecutable()) + return info.absoluteFilePath(); + + // Does the OS have some weird extension concept or does the + // binary have a 3 letter extension? + if (pathOS == OS_Unix) + return QString(); + const int dotIndex = binary.lastIndexOf(QLatin1Char('.')); + if (dotIndex != -1 && dotIndex == binary.size() - 4) + return QString(); + + switch (pathOS) { + case OS_Unix: + break; + case OS_Windows: { + static const char *windowsExtensions[] = {".cmd", ".bat", ".exe", ".com" }; + // Check the Windows extensions using the order + const int windowsExtensionCount = sizeof(windowsExtensions)/sizeof(const char*); + for (int e = 0; e < windowsExtensionCount; e ++) { + const QFileInfo windowsBinary(dir.filePath(binary + QLatin1String(windowsExtensions[e]))); + if (windowsBinary.isFile() && windowsBinary.isExecutable()) + return windowsBinary.absoluteFilePath(); + } + } + break; + case OS_Mac: { + // Check for Mac app folders + const QFileInfo appFolder(dir.filePath(binary + QLatin1String(".app"))); + if (appFolder.isDir()) { + QString macBinaryPath = appFolder.absoluteFilePath(); + macBinaryPath += QLatin1String("/Contents/MacOS/"); + macBinaryPath += binary; + const QFileInfo macBinary(macBinaryPath); + if (macBinary.isFile() && macBinary.isExecutable()) + return macBinary.absoluteFilePath(); + } + } + break; + } + return QString(); +} + +QString SynchronousProcess::locateBinary(const QString &path, const QString &binary) +{ + // Absolute file? + const QFileInfo absInfo(binary); + if (absInfo.isAbsolute()) + return checkBinary(absInfo.dir(), absInfo.fileName()); + + // Windows finds binaries in the current directory + if (pathOS == OS_Windows) { + const QString currentDirBinary = checkBinary(QDir::current(), binary); + if (!currentDirBinary.isEmpty()) + return currentDirBinary; + } + + const QStringList paths = path.split(pathSeparator()); + if (paths.empty()) + return QString(); + const QStringList::const_iterator cend = paths.constEnd(); + for (QStringList::const_iterator it = paths.constBegin(); it != cend; ++it) { + const QDir dir(*it); + const QString rc = checkBinary(dir, binary); + if (!rc.isEmpty()) + return rc; + } + return QString(); +} + +QString SynchronousProcess::locateBinary(const QString &binary) +{ + const QByteArray path = qgetenv("PATH"); + return locateBinary(QString::fromLocal8Bit(path), binary); +} + +QChar SynchronousProcess::pathSeparator() +{ + if (pathOS == OS_Windows) + return QLatin1Char(';'); + return QLatin1Char(':'); +} + + } // namespace Utils } // namespace Core diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h index e9218f43d80..80a04a1303e 100644 --- a/src/libs/utils/synchronousprocess.h +++ b/src/libs/utils/synchronousprocess.h @@ -114,6 +114,12 @@ public: SynchronousProcessResponse run(const QString &binary, const QStringList &args); + // Helpers to find binaries. Do not use it for other path variables + // and file types. + static QString locateBinary(const QString &binary); + static QString locateBinary(const QString &path, const QString &binary); + static QChar pathSeparator(); + signals: void stdOut(const QByteArray &data, bool firstTime); void stdErr(const QByteArray &data, bool firstTime); diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 87f06931200..a3ad3ba84ff 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -102,8 +102,10 @@ GitClient::GitClient(GitPlugin* plugin) m_plugin(plugin), m_core(Core::ICore::instance()) { - if (QSettings *s = m_core->settings()) + if (QSettings *s = m_core->settings()) { m_settings.fromSettings(s); + m_binaryPath = m_settings.gitBinaryPath(); + } } GitClient::~GitClient() @@ -478,7 +480,7 @@ GitCommand *GitClient::createCommand(const QString &workingDirectory, if (m_settings.adoptPath) environment.set(QLatin1String("PATH"), m_settings.path); - GitCommand* command = new GitCommand(workingDirectory, environment); + GitCommand* command = new GitCommand(m_binaryPath, workingDirectory, environment); if (outputToWindow) { if (!editor) { // assume that the commands output is the important thing connect(command, SIGNAL(outputData(QByteArray)), this, SLOT(appendDataAndPopup(QByteArray))); @@ -527,10 +529,9 @@ bool GitClient::synchronousGit(const QString &workingDirectory, { if (Git::Constants::debug) qDebug() << "synchronousGit" << workingDirectory << arguments; - const QString binary = QLatin1String(Constants::GIT_BINARY); if (logCommandToWindow) - m_plugin->outputWindow()->append(formatCommand(binary, arguments)); + m_plugin->outputWindow()->append(formatCommand(m_binaryPath, arguments)); QProcess process; process.setWorkingDirectory(workingDirectory); @@ -540,7 +541,7 @@ bool GitClient::synchronousGit(const QString &workingDirectory, environment.set(QLatin1String("PATH"), m_settings.path); process.setEnvironment(environment.toStringList()); - process.start(binary, arguments); + process.start(m_binaryPath, arguments); if (!process.waitForFinished()) { if (errorText) *errorText = "Error: Git timed out"; @@ -1000,6 +1001,6 @@ void GitClient::setSettings(const GitSettings &s) m_settings = s; if (QSettings *s = m_core->settings()) m_settings.toSettings(s); + m_binaryPath = m_settings.gitBinaryPath(); } } - diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index c920ffc1b32..edd7e05c9e3 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -176,6 +176,7 @@ private: GitPlugin *m_plugin; Core::ICore *m_core; GitSettings m_settings; + QString m_binaryPath; }; diff --git a/src/plugins/git/gitcommand.cpp b/src/plugins/git/gitcommand.cpp index 8362926cecc..54bfcea2ab4 100644 --- a/src/plugins/git/gitcommand.cpp +++ b/src/plugins/git/gitcommand.cpp @@ -61,8 +61,10 @@ GitCommand::Job::Job(const QStringList &a, int t) : { } -GitCommand::GitCommand(const QString &workingDirectory, +GitCommand::GitCommand(const QString &binaryPath, + const QString &workingDirectory, ProjectExplorer::Environment &environment) : + m_binaryPath(binaryPath), m_workingDirectory(workingDirectory), m_environment(environmentToList(environment)) { @@ -109,7 +111,7 @@ void GitCommand::run() if (Git::Constants::debug) qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments; - process.start(QLatin1String(Constants::GIT_BINARY), m_jobs.at(j).arguments); + process.start(m_binaryPath, m_jobs.at(j).arguments); if (!process.waitForFinished(m_jobs.at(j).timeout * 1000)) { ok = false; error += QLatin1String("Error: Git timed out"); diff --git a/src/plugins/git/gitcommand.h b/src/plugins/git/gitcommand.h index 32b76bf3485..1d661706151 100644 --- a/src/plugins/git/gitcommand.h +++ b/src/plugins/git/gitcommand.h @@ -43,9 +43,11 @@ namespace Internal { class GitCommand : public QObject { + Q_DISABLE_COPY(GitCommand) Q_OBJECT public: - explicit GitCommand(const QString &workingDirectory, + explicit GitCommand(const QString &binaryPath, + const QString &workingDirectory, ProjectExplorer::Environment &environment); @@ -67,8 +69,7 @@ private: int timeout; }; - QStringList environment() const; - + const QString m_binaryPath; const QString m_workingDirectory; const QStringList m_environment; diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index 02a1acc1d9e..c379bb3fba5 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -32,9 +32,13 @@ ***************************************************************************/ #include "gitsettings.h" +#include "gitconstants.h" + +#include #include #include +#include static const char *groupC = "Git"; static const char *sysEnvKeyC = "SysEnv"; @@ -79,5 +83,30 @@ bool GitSettings::equals(const GitSettings &s) const return adoptPath == s.adoptPath && path == s.path && logCount == s.logCount && timeout == s.timeout; } +QString GitSettings::gitBinaryPath(bool *ok, QString *errorMessage) const +{ + // Locate binary in path if one is specified, otherwise default + // to pathless binary + if (ok) + *ok = true; + if (errorMessage) + errorMessage->clear(); + const QString binary = QLatin1String(Constants::GIT_BINARY); + // Easy, git is assumed to be elsewhere accessible + if (!adoptPath) + return binary; + // Search in path? + const QString pathBinary = Core::Utils::SynchronousProcess::locateBinary(path, binary); + if (pathBinary.isEmpty()) { + if (ok) + *ok = false; + if (errorMessage) + *errorMessage = QCoreApplication::translate("GitSettings", + "The binary '%1' could not be located in the path '%2'").arg(binary, path); + return binary; + } + return pathBinary; +} + } } diff --git a/src/plugins/git/gitsettings.h b/src/plugins/git/gitsettings.h index c2463eb326d..05dc250c578 100644 --- a/src/plugins/git/gitsettings.h +++ b/src/plugins/git/gitsettings.h @@ -51,6 +51,8 @@ struct GitSettings void fromSettings(QSettings *); void toSettings(QSettings *) const; + QString gitBinaryPath(bool *ok = 0, QString *errorMessage = 0) const; + bool equals(const GitSettings &s) const; bool adoptPath; diff --git a/src/plugins/git/settingspage.cpp b/src/plugins/git/settingspage.cpp index 121c7cd889b..4fdd672eac4 100644 --- a/src/plugins/git/settingspage.cpp +++ b/src/plugins/git/settingspage.cpp @@ -36,8 +36,10 @@ #include "gitplugin.h" #include +#include -using namespace Git::Internal; +namespace Git { +namespace Internal { SettingsPageWidget::SettingsPageWidget(QWidget *parent) : QWidget(parent) @@ -101,6 +103,17 @@ void SettingsPage::apply() { if (!m_widget) return; + const GitSettings newSettings = m_widget->settings(); + // Warn if git cannot be found in path if the widget is on top + if (m_widget->isVisible()) { + bool gitFoundOk; + QString errorMessage; + newSettings.gitBinaryPath(&gitFoundOk, &errorMessage); + if (!gitFoundOk) + QMessageBox::warning(m_widget, tr("Git Settings"), errorMessage); + } - GitPlugin::instance()->setSettings(m_widget->settings()); + GitPlugin::instance()->setSettings(newSettings); +} +} } From 349e2d68bf482afcd3a54ec3ce466e837b8f5b0f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 19 Feb 2009 17:30:48 +0100 Subject: [PATCH 4/6] Initial work on unqualified and qualified name lookup. --- tests/manual/binding/main.cpp | 144 +++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 4 deletions(-) diff --git a/tests/manual/binding/main.cpp b/tests/manual/binding/main.cpp index 8e889b6b514..77aa298b0e0 100644 --- a/tests/manual/binding/main.cpp +++ b/tests/manual/binding/main.cpp @@ -43,6 +43,8 @@ #include #include +#include + #include #include #include @@ -79,6 +81,11 @@ public: /// Returns the binding associated with the given symbol. NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); + NamespaceBinding *resolveNamespace(QualifiedNameId *q, unsigned index, + unsigned count); + + NamespaceBinding *resolveNamespace(Name *name, bool lookAtParent = true); + /// Helpers. std::string qualifiedId() const; void dump(); @@ -96,6 +103,9 @@ public: // attributes /// This binding's connections. Array children; + /// This binding's usings + Array usings; + /// This binding's namespace symbols. Array symbols; }; @@ -211,6 +221,99 @@ NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symb return binding; } +static void closure(NamespaceBinding *binding, Name *name, + Array *bindings) +{ + for (unsigned i = 0; i < bindings->size(); ++i) { + NamespaceBinding *b = bindings->at(i); + + if (b == binding) + return; + } + + bindings->push_back(binding); + + assert(name->isNameId()); + + Identifier *id = name->asNameId()->identifier(); + bool ignoreUsingDirectives = false; + + for (unsigned i = 0; i < binding->symbols.size(); ++i) { + Namespace *symbol = binding->symbols.at(i); + Scope *scope = symbol->members(); + + for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) { + if (symbol->isUsingDeclaration() || symbol->isUsingNamespaceDirective()) + continue; + + //printf("found declaration at %s:%d\n", symbol->fileName(), symbol->line()); + + // ### FIXME: ignoreUsingDirectives = true; + break; + } + } + + if (ignoreUsingDirectives) + return; + + for (unsigned i = 0; i < binding->usings.size(); ++i) { + NamespaceBinding *u = binding->usings.at(i); + + closure(u, name, bindings); + } +} + + +NamespaceBinding *NamespaceBinding::resolveNamespace(Name *name, bool lookAtParent) +{ + if (! name) + return 0; + + else if (NameId *nameId = name->asNameId()) { + Array bindings; + closure(this, nameId, &bindings); + + Array results; + + for (unsigned i = 0; i < bindings.size(); ++i) { + NamespaceBinding *binding = bindings.at(i); + + if (NamespaceBinding *b = binding->findNamespaceBinding(nameId)) + results.push_back(b); + } + + if (results.size() == 1) + return results.at(0); + + else if (results.size() > 1) { + // ### FIXME: return 0; + return results.at(0); + } + + else if (parent && lookAtParent) + return parent->resolveNamespace(name); + + } else if (QualifiedNameId *q = name->asQualifiedNameId()) { + if (q->nameCount() == 1) { + assert(q->isGlobal()); + + return globalNamespaceBinding()->resolveNamespace(q->nameAt(0)); + } + + NamespaceBinding *current = this; + if (q->isGlobal()) + current = globalNamespaceBinding(); + + current = current->resolveNamespace(q->nameAt(0)); + for (unsigned i = 1; current && i < q->nameCount(); ++i) + current = current->resolveNamespace(q->nameAt(i), false); + + return current; + } + + return 0; +} + // ### rewrite me std::string NamespaceBinding::qualifiedId() const { @@ -255,28 +358,38 @@ public: Binder(); virtual ~Binder(); - NamespaceBinding *operator()(Symbol *symbol) - { return bind(symbol, 0); } + NamespaceBinding *operator()(TranslationUnit *u, Namespace *globals) + { + TranslationUnit *previousUnit = unit; + unit = u; + NamespaceBinding *binding = bind(globals, 0); + unit = previousUnit; + return binding; + } protected: NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding); NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); + NamespaceBinding *resolveNamespace(Name *name); NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding); using SymbolVisitor::visit; virtual bool visit(Namespace *); + virtual bool visit(UsingNamespaceDirective *); virtual bool visit(Class *); virtual bool visit(Function *); virtual bool visit(Block *); private: NamespaceBinding *namespaceBinding; + TranslationUnit *unit; }; Binder::Binder() - : namespaceBinding(0) + : namespaceBinding(0), + unit(0) { } Binder::~Binder() @@ -299,6 +412,15 @@ NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol) return namespaceBinding; } +NamespaceBinding *Binder::resolveNamespace(Name *name) +{ + if (! namespaceBinding) + return 0; + + return namespaceBinding->resolveNamespace(name); +} + + NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding) { NamespaceBinding *previousBinding = namespaceBinding; @@ -319,6 +441,20 @@ bool Binder::visit(Namespace *symbol) return false; } +bool Binder::visit(UsingNamespaceDirective *u) +{ + NamespaceBinding *resolved = resolveNamespace(u->name()); + + if (! resolved) { + unit->error(u->sourceLocation(), "expected namespace-name"); + return false; + } + + namespaceBinding->usings.push_back(resolved); + + return false; +} + bool Binder::visit(Class *) { return false; } @@ -376,7 +512,7 @@ int main(int argc, char *argv[]) // bind Binder bind; - NamespaceBinding *binding = bind(globalNamespace); + NamespaceBinding *binding = bind(&unit, globalNamespace); binding->dump(); delete binding; From 47f27ee7f51235d7189d0041089f270481407c2b Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 19 Feb 2009 18:26:10 +0100 Subject: [PATCH 5/6] We need to look at the symbol's location to implement the qualified name lookup. --- tests/manual/binding/main.cpp | 80 ++++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/tests/manual/binding/main.cpp b/tests/manual/binding/main.cpp index 77aa298b0e0..72b6fba4f32 100644 --- a/tests/manual/binding/main.cpp +++ b/tests/manual/binding/main.cpp @@ -57,6 +57,40 @@ // NamespaceBinding //////////////////////////////////////////////////////////////////////////////// +class Location +{ +public: + Location() + : _fileId(0), + _sourceLocation(0) + { } + + Location(Symbol *symbol) + : _fileId(symbol->fileId()), + _sourceLocation(symbol->sourceLocation()) + { } + + Location(StringLiteral *fileId, unsigned sourceLocation) + : _fileId(fileId), _sourceLocation(sourceLocation) + { } + + inline bool isValid() const + { return _fileId != 0; } + + inline operator bool() const + { return _fileId != 0; } + + inline StringLiteral *fileId() const + { return _fileId; } + + inline unsigned sourceLocation() const + { return _sourceLocation; } + +private: + StringLiteral *_fileId; + unsigned _sourceLocation; +}; + class NamespaceBinding { public: @@ -81,10 +115,9 @@ public: /// Returns the binding associated with the given symbol. NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); - NamespaceBinding *resolveNamespace(QualifiedNameId *q, unsigned index, - unsigned count); - - NamespaceBinding *resolveNamespace(Name *name, bool lookAtParent = true); + NamespaceBinding *resolveNamespace(const Location &loc, + Name *name, + bool lookAtParent = true); /// Helpers. std::string qualifiedId() const; @@ -103,7 +136,7 @@ public: // attributes /// This binding's connections. Array children; - /// This binding's usings + /// This binding's list of using namespaces. Array usings; /// This binding's namespace symbols. @@ -221,7 +254,8 @@ NamespaceBinding *NamespaceBinding::findOrCreateNamespaceBinding(Namespace *symb return binding; } -static void closure(NamespaceBinding *binding, Name *name, +static void closure(const Location &loc, + NamespaceBinding *binding, Name *name, Array *bindings) { for (unsigned i = 0; i < bindings->size(); ++i) { @@ -243,13 +277,15 @@ static void closure(NamespaceBinding *binding, Name *name, Scope *scope = symbol->members(); for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) { - if (symbol->isUsingDeclaration() || symbol->isUsingNamespaceDirective()) + if (! symbol->isNamespace()) continue; - //printf("found declaration at %s:%d\n", symbol->fileName(), symbol->line()); + const Location l(symbol); - // ### FIXME: ignoreUsingDirectives = true; - break; + if (l.fileId() == loc.fileId() && l.sourceLocation() < loc.sourceLocation()) { + ignoreUsingDirectives = true; + break; + } } } @@ -259,19 +295,21 @@ static void closure(NamespaceBinding *binding, Name *name, for (unsigned i = 0; i < binding->usings.size(); ++i) { NamespaceBinding *u = binding->usings.at(i); - closure(u, name, bindings); + closure(loc, u, name, bindings); } } -NamespaceBinding *NamespaceBinding::resolveNamespace(Name *name, bool lookAtParent) +NamespaceBinding *NamespaceBinding::resolveNamespace(const Location &loc, + Name *name, + bool lookAtParent) { if (! name) return 0; else if (NameId *nameId = name->asNameId()) { Array bindings; - closure(this, nameId, &bindings); + closure(loc, this, nameId, &bindings); Array results; @@ -291,22 +329,22 @@ NamespaceBinding *NamespaceBinding::resolveNamespace(Name *name, bool lookAtPare } else if (parent && lookAtParent) - return parent->resolveNamespace(name); + return parent->resolveNamespace(loc, name); } else if (QualifiedNameId *q = name->asQualifiedNameId()) { if (q->nameCount() == 1) { assert(q->isGlobal()); - return globalNamespaceBinding()->resolveNamespace(q->nameAt(0)); + return globalNamespaceBinding()->resolveNamespace(loc, q->nameAt(0)); } NamespaceBinding *current = this; if (q->isGlobal()) current = globalNamespaceBinding(); - current = current->resolveNamespace(q->nameAt(0)); + current = current->resolveNamespace(loc, q->nameAt(0)); for (unsigned i = 1; current && i < q->nameCount(); ++i) - current = current->resolveNamespace(q->nameAt(i), false); + current = current->resolveNamespace(loc, q->nameAt(i), false); return current; } @@ -370,7 +408,7 @@ public: protected: NamespaceBinding *bind(Symbol *symbol, NamespaceBinding *binding); NamespaceBinding *findOrCreateNamespaceBinding(Namespace *symbol); - NamespaceBinding *resolveNamespace(Name *name); + NamespaceBinding *resolveNamespace(const Location &loc, Name *name); NamespaceBinding *switchNamespaceBinding(NamespaceBinding *binding); @@ -412,12 +450,12 @@ NamespaceBinding *Binder::findOrCreateNamespaceBinding(Namespace *symbol) return namespaceBinding; } -NamespaceBinding *Binder::resolveNamespace(Name *name) +NamespaceBinding *Binder::resolveNamespace(const Location &loc, Name *name) { if (! namespaceBinding) return 0; - return namespaceBinding->resolveNamespace(name); + return namespaceBinding->resolveNamespace(loc, name); } @@ -443,7 +481,7 @@ bool Binder::visit(Namespace *symbol) bool Binder::visit(UsingNamespaceDirective *u) { - NamespaceBinding *resolved = resolveNamespace(u->name()); + NamespaceBinding *resolved = resolveNamespace(Location(u), u->name()); if (! resolved) { unit->error(u->sourceLocation(), "expected namespace-name"); From 4a259547fc5a8e456ca47c1fd218dae028c9e271 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Thu, 19 Feb 2009 18:31:46 +0100 Subject: [PATCH 6/6] Oops! check the symbol's name :-) --- tests/manual/binding/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/manual/binding/main.cpp b/tests/manual/binding/main.cpp index 72b6fba4f32..5c3545339e1 100644 --- a/tests/manual/binding/main.cpp +++ b/tests/manual/binding/main.cpp @@ -277,7 +277,7 @@ static void closure(const Location &loc, Scope *scope = symbol->members(); for (Symbol *symbol = scope->lookat(id); symbol; symbol = symbol->next()) { - if (! symbol->isNamespace()) + if (symbol->name() != name || ! symbol->isNamespace()) continue; const Location l(symbol);