Index: include/clang/Sema/CodeCompleteConsumer.h =================================================================== --- include/clang/Sema/CodeCompleteConsumer.h +++ include/clang/Sema/CodeCompleteConsumer.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/Type.h" #include "clang/Sema/CodeCompleteOptions.h" +#include "clang/Sema/DeclSpec.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -280,6 +281,10 @@ /// \brief The identifiers for Objective-C selector parts. ArrayRef SelIdents; + /// \brief The scope specifier that comes before the completion token e.g. + /// "a::b::" + llvm::Optional ScopeSpecifier; + public: /// \brief Construct a new code-completion context of the given kind. CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { } @@ -315,8 +320,20 @@ /// \brief Determines whether we want C++ constructors as results within this /// context. bool wantConstructorResults() const; -}; + /// \brief Sets the scope specifier that comes before the completion token. + /// This is expected to be set in code completions on qualfied specifiers + /// (e.g. "a::b::"). + void setCXXScopeSpecifier(CXXScopeSpec SS) { + this->ScopeSpecifier = std::move(SS); + } + + llvm::Optional getCXXScopeSpecifier() { + if (ScopeSpecifier) + return ScopeSpecifier.getPointer(); + return llvm::None; + } +}; /// \brief A "string" used to describe how code completion can /// be performed for an entity. Index: lib/Sema/SemaCodeComplete.cpp =================================================================== --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -4603,9 +4603,19 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext) { - if (!SS.getScopeRep() || !CodeCompleter) + if (SS.isEmpty() || !CodeCompleter) return; + // We want to keep the scope specifier even if it's invalid (e.g. the scope + // "a::b::" is not corresponding to any context/namespace in the AST), since + // it can be useful for global code completion which have information about + // contexts/symbols that are not in the AST. + if (SS.isInvalid()) { + CodeCompletionContext CC(CodeCompletionContext::CCC_Name); + CC.setCXXScopeSpecifier(SS); + HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0); + return; + } // Always pretend to enter a context to ensure that a dependent type // resolves to a dependent record. DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true); @@ -4621,7 +4631,7 @@ CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Name); Results.EnterNewScope(); - + // The "template" keyword can follow "::" in the grammar, but only // put it into the grammar if the nested-name-specifier is dependent. NestedNameSpecifier *NNS = SS.getScopeRep(); @@ -4635,16 +4645,18 @@ // qualified-id completions. if (!EnteringContext) MaybeAddOverrideCalls(*this, Ctx, Results); - Results.ExitScope(); - + Results.ExitScope(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, /*IncludeGlobalScope=*/true, /*IncludeDependentBases=*/true); - HandleCodeCompleteResults(this, CodeCompleter, - Results.getCompletionContext(), - Results.data(),Results.size()); + auto CC = Results.getCompletionContext(); + CC.setCXXScopeSpecifier(SS); + + HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(), + Results.size()); } void Sema::CodeCompleteUsing(Scope *S) {