diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index bcfe168e810..19c99ae491d 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -2965,6 +2965,8 @@ bool Bind::visit(EnumSpecifierAST *ast) Enum *e = control()->newEnum(sourceLocation, enumName); e->setStartOffset(tokenAt(sourceLocation).end()); // at the end of the enum or identifier token. e->setEndOffset(tokenAt(ast->lastToken() - 1).end()); + if (ast->key_token) + e->setScoped(true); ast->symbol = e; _scope->addMember(e); diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp index e47a405767f..1a16c5ed7ff 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.cpp +++ b/src/libs/3rdparty/cplusplus/Symbols.cpp @@ -421,10 +421,12 @@ void Block::visitSymbol0(SymbolVisitor *visitor) Enum::Enum(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Scope(translationUnit, sourceLocation, name) + , _isScoped(false) { } Enum::Enum(Clone *clone, Subst *subst, Enum *original) : Scope(clone, subst, original) + , _isScoped(original->isScoped()) { } Enum::~Enum() @@ -447,6 +449,16 @@ bool Enum::isEqualTo(const Type *other) const return l->isEqualTo(r); } +bool Enum::isScoped() const +{ + return _isScoped; +} + +void Enum::setScoped(bool scoped) +{ + _isScoped = scoped; +} + void Enum::accept0(TypeVisitor *visitor) { visitor->visit(this); } diff --git a/src/libs/3rdparty/cplusplus/Symbols.h b/src/libs/3rdparty/cplusplus/Symbols.h index 097a7f7d030..b6a711b8f87 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.h +++ b/src/libs/3rdparty/cplusplus/Symbols.h @@ -279,10 +279,16 @@ public: virtual Enum *asEnumType() { return this; } + bool isScoped() const; + void setScoped(bool scoped); + protected: virtual void visitSymbol0(SymbolVisitor *visitor); virtual void accept0(TypeVisitor *visitor); virtual bool matchType0(const Type *otherType, TypeMatcher *matcher) const; + +private: + bool _isScoped; }; class CPLUSPLUS_EXPORT Function: public Scope, public Type diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 50d9655b231..4b2748f7fe7 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -83,6 +83,9 @@ static void path_helper(Symbol *symbol, QList *names) } else if (symbol->isFunction()) { if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) addNames(q->base(), names); + } else if (Enum *e = symbol->asEnum()) { + if (e->isScoped()) + addNames(symbol->name(), names); } } } @@ -349,17 +352,10 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const if (! candidates.isEmpty()) return candidates; // it's a template parameter. - } else if (Class *klass = scope->asClass()) { - - if (ClassOrNamespace *binding = bindings()->lookupType(klass)) { - candidates = binding->find(name); - - if (! candidates.isEmpty()) - return candidates; - } - - } else if (Namespace *ns = scope->asNamespace()) { - if (ClassOrNamespace *binding = bindings()->lookupType(ns)) + } else if (scope->asNamespace() + || scope->asClass() + || (scope->asEnum() && scope->asEnum()->isScoped())) { + if (ClassOrNamespace *binding = bindings()->lookupType(scope)) candidates = binding->find(name); if (! candidates.isEmpty()) @@ -419,7 +415,7 @@ QList ClassOrNamespace::usings() const return _usings; } -QList ClassOrNamespace::enums() const +QList ClassOrNamespace::unscopedEnums() const { const_cast(this)->flush(); return _enums; @@ -547,7 +543,7 @@ void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding } } - foreach (Enum *e, binding->enums()) + foreach (Enum *e, binding->unscopedEnums()) _factory->lookupInScope(name, e, result, templateId, binding); foreach (ClassOrNamespace *u, binding->usings()) @@ -753,7 +749,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac instantiation->_instantiationOrigin = origin; // The instantiation should have all symbols, enums, and usings from the reference. - instantiation->_enums.append(reference->enums()); + instantiation->_enums.append(reference->unscopedEnums()); instantiation->_usings.append(reference->usings()); // It gets a bit complicated if the reference is actually a class template because we @@ -917,7 +913,7 @@ void ClassOrNamespace::addTodo(Symbol *symbol) _todo.append(symbol); } -void ClassOrNamespace::addEnum(Enum *e) +void ClassOrNamespace::addUnscopedEnum(Enum *e) { _enums.append(e); } @@ -1126,7 +1122,12 @@ bool CreateBindings::visit(ForwardClassDeclaration *klass) bool CreateBindings::visit(Enum *e) { - _currentClassOrNamespace->addEnum(e); + if (e->isScoped()) { + ClassOrNamespace *previous = enterClassOrNamespaceBinding(e); + _currentClassOrNamespace = previous; + } else { + _currentClassOrNamespace->addUnscopedEnum(e); + } return false; } diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 0022d138d7e..ef591a37931 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -90,7 +90,7 @@ public: ClassOrNamespace *parent() const; QList usings() const; - QList enums() const; + QList unscopedEnums() const; QList symbols() const; ClassOrNamespace *globalNamespace() const; @@ -110,7 +110,7 @@ private: void addTodo(Symbol *symbol); void addSymbol(Symbol *symbol); - void addEnum(Enum *e); + void addUnscopedEnum(Enum *e); void addUsing(ClassOrNamespace *u); void addNestedType(const Name *alias, ClassOrNamespace *e); diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index 321d05c98fc..d3f915d0991 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -1407,10 +1407,10 @@ void CppCompletionAssistProcessor::globalCompletion(CPlusPlus::Scope *currentSco const QList symbols = currentBinding->symbols(); if (! symbols.isEmpty()) { - if (symbols.first()->isNamespace()) - completeNamespace(currentBinding); - else + if (symbols.first()->isClass()) completeClass(currentBinding); + else + completeNamespace(currentBinding); } } @@ -1480,6 +1480,12 @@ bool CppCompletionAssistProcessor::completeScope(const QListasEnumType()) { + if (ClassOrNamespace *b = context.lookupType(e)) { + completeNamespace(b); + break; + } } } @@ -1504,11 +1510,11 @@ void CppCompletionAssistProcessor::completeNamespace(CPlusPlus::ClassOrNamespace QSet scopesVisited; foreach (Symbol *bb, binding->symbols()) { - if (Namespace *ns = bb->asNamespace()) - scopesToVisit.append(ns); + if (Scope *scope = bb->asScope()) + scopesToVisit.append(scope); } - foreach (Enum *e, binding->enums()) { + foreach (Enum *e, binding->unscopedEnums()) { scopesToVisit.append(e); } @@ -1549,7 +1555,7 @@ void CppCompletionAssistProcessor::completeClass(CPlusPlus::ClassOrNamespace *b, scopesToVisit.append(k); } - foreach (Enum *e, binding->enums()) + foreach (Enum *e, binding->unscopedEnums()) scopesToVisit.append(e); while (! scopesToVisit.isEmpty()) {