diff options
-rw-r--r-- | include/clang/Driver/CC1Options.td | 2 | ||||
-rw-r--r-- | include/clang/Frontend/CompilerInstance.h | 3 | ||||
-rw-r--r-- | include/clang/Frontend/FrontendOptions.h | 3 | ||||
-rw-r--r-- | include/clang/Sema/CodeCompleteConsumer.h | 29 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 10 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 96 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 57 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 39 | ||||
-rw-r--r-- | test/Index/complete-exprs.c | 6 | ||||
-rw-r--r-- | tools/libclang/CIndexCodeCompletion.cpp | 3 |
12 files changed, 214 insertions, 46 deletions
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index bfa8c8ba02..ea7175da53 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -264,6 +264,8 @@ def code_completion_macros : Flag<"-code-completion-macros">, HelpText<"Include macros in code-completion results">; def code_completion_patterns : Flag<"-code-completion-patterns">, HelpText<"Include code patterns in code-completion results">; +def no_code_completion_globals : Flag<"-no-code-completion-globals">, + HelpText<"Do not include global declarations in code-completion results.">; def disable_free : Flag<"-disable-free">, HelpText<"Disable freeing of memory on exit">; def help : Flag<"-help">, diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index bd1791dae8..2a0a7a7747 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -544,7 +544,8 @@ public: createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, unsigned Line, unsigned Column, bool UseDebugPrinter, bool ShowMacros, - bool ShowCodePatterns, llvm::raw_ostream &OS); + bool ShowCodePatterns, bool ShowGlobals, + llvm::raw_ostream &OS); /// \brief Create the Sema object to be used for parsing. void createSema(bool CompleteTranslationUnit, diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 48ce5074fa..e24f3a0be1 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -69,6 +69,8 @@ public: /// results. unsigned ShowCodePatternsInCodeCompletion : 1; ///< Show code patterns in code /// completion results. + unsigned ShowGlobalSymbolsInCodeCompletion : 1; ///< Show top-level decls in + /// code completion results. unsigned ShowStats : 1; ///< Show frontend performance /// metrics and statistics. unsigned ShowTimers : 1; ///< Show timers for individual @@ -122,6 +124,7 @@ public: ShowHelp = 0; ShowMacrosInCodeCompletion = 0; ShowCodePatternsInCodeCompletion = 0; + ShowGlobalSymbolsInCodeCompletion = 1; ShowStats = 0; ShowTimers = 0; ShowVersion = 0; diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 48e422383f..16dd69d401 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -127,7 +127,12 @@ public: /// to indicate a struct or class name. CCC_ClassOrStructTag, /// \brief Code completion occurred where a protocol name is expected. - CCC_ObjCProtocolName + CCC_ObjCProtocolName, + /// \brief Code completion occurred where a namespace or namespace alias + /// is expected. + CCC_Namespace, + /// \brief Code completion occurred where a type name is expected. + CCC_Type }; private: @@ -382,6 +387,10 @@ protected: /// the completion results. bool IncludeCodePatterns; + /// \brief Whether to include global (top-level) declarations and names in + /// the completion results. + bool IncludeGlobals; + /// \brief Whether the output format for the code-completion consumer is /// binary. bool OutputIsBinary; @@ -588,12 +597,12 @@ public: }; CodeCompleteConsumer() : IncludeMacros(false), IncludeCodePatterns(false), - OutputIsBinary(false) { } + IncludeGlobals(true), OutputIsBinary(false) { } CodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, - bool OutputIsBinary) + bool IncludeGlobals, bool OutputIsBinary) : IncludeMacros(IncludeMacros), IncludeCodePatterns(IncludeCodePatterns), - OutputIsBinary(OutputIsBinary) { } + IncludeGlobals(IncludeGlobals), OutputIsBinary(OutputIsBinary) { } /// \brief Whether the code-completion consumer wants to see macros. bool includeMacros() const { return IncludeMacros; } @@ -601,6 +610,9 @@ public: /// \brief Whether the code-completion consumer wants to see code patterns. bool includeCodePatterns() const { return IncludeCodePatterns; } + /// \brief Whether to include global (top-level) declaration results. + bool includeGlobals() const { return IncludeGlobals; } + /// \brief Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } @@ -639,8 +651,10 @@ public: /// \brief Create a new printing code-completion consumer that prints its /// results to the given raw output stream. PrintingCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, + bool IncludeGlobals, llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, false), OS(OS) {} + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, + false), OS(OS) {} /// \brief Prints the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, @@ -664,8 +678,9 @@ public: /// results to the given raw output stream in a format readable to the CIndex /// library. CIndexCodeCompleteConsumer(bool IncludeMacros, bool IncludeCodePatterns, - llvm::raw_ostream &OS) - : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, true), OS(OS) {} + bool IncludeGlobals, llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, + true), OS(OS) {} /// \brief Prints the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 5ef8e5f070..a57a5a78c7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1486,7 +1486,9 @@ public: /// C99 6.2.2p4-5 and C++ [basic.link]p6. LookupRedeclarationWithLinkage, /// Look up the name of an Objective-C protocol. - LookupObjCProtocolName + LookupObjCProtocolName, + /// \brief Look up any declaration with any name. + LookupAnyName }; /// \brief Specifies whether (or how) name lookup is being performed for a @@ -1534,9 +1536,11 @@ public: ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, - VisibleDeclConsumer &Consumer); + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope = true); void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, - VisibleDeclConsumer &Consumer); + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope = true); /// \brief The context in which typo-correction occurs. /// diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index e6bae6b727..8d49d4e786 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -88,6 +88,79 @@ void ASTUnit::CleanTemporaryFiles() { TemporaryFiles.clear(); } +/// \brief Determine the set of code-completion contexts in which this +/// declaration should be shown. +static unsigned getDeclShowContexts(NamedDecl *ND, + const LangOptions &LangOpts) { + if (isa<UsingShadowDecl>(ND)) + ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl()); + if (!ND) + return 0; + + unsigned Contexts = 0; + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || + isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) { + // Types can appear in these contexts. + if (LangOpts.CPlusPlus || !isa<TagDecl>(ND)) + Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Type - 1)); + + // In C++, types can appear in expressions contexts (for functional casts). + if (LangOpts.CPlusPlus) + Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1)); + + // In Objective-C, message sends can send interfaces. In Objective-C++, + // all types are available due to functional casts. + if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) + Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); + + // Deal with tag names. + if (isa<EnumDecl>(ND)) { + Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1)); + + // Part of the nested-name-specifier. + if (LangOpts.CPlusPlus0x) + Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1)); + } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) { + if (Record->isUnion()) + Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1)); + else + Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)); + + // Part of the nested-name-specifier. + if (LangOpts.CPlusPlus) + Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1)); + } + } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { + // Values can appear in these contexts. + Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)); + } else if (isa<ObjCProtocolDecl>(ND)) { + Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1)); + } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { + Contexts = (1 << (CodeCompletionContext::CCC_TopLevel - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1)) + | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1)) + | (1 << (CodeCompletionContext::CCC_Statement - 1)) + | (1 << (CodeCompletionContext::CCC_Expression - 1)) + | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1)) + | (1 << (CodeCompletionContext::CCC_Namespace - 1)); + + // Part of the nested-name-specifier. + Contexts |= (1 << (CodeCompletionContext::CCC_MemberAccess - 1)) + | (1 << (CodeCompletionContext::CCC_EnumTag - 1)) + | (1 << (CodeCompletionContext::CCC_UnionTag - 1)) + | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1)) + | (1 << (CodeCompletionContext::CCC_Type - 1)); + } + + return Contexts; +} + void ASTUnit::CacheCodeCompletionResults() { if (!TheSema) return; @@ -111,10 +184,17 @@ void ASTUnit::CacheCodeCompletionResults() { // Translate global code completions into cached completions. for (unsigned I = 0, N = Results.size(); I != N; ++I) { switch (Results[I].Kind) { - case Result::RK_Declaration: - // FIXME: Handle declarations! + case Result::RK_Declaration: { + CachedCodeCompletionResult CachedResult; + CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema); + CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration, + Ctx->getLangOptions()); + CachedResult.Priority = Results[I].Priority; + CachedResult.Kind = Results[I].CursorKind; + CachedCompletionResults.push_back(CachedResult); break; - + } + case Result::RK_Keyword: case Result::RK_Pattern: // Ignore keywords and patterns; we don't care, since they are so @@ -1287,8 +1367,9 @@ namespace { public: AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, - bool IncludeMacros, bool IncludeCodePatterns) - : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, + bool IncludeMacros, bool IncludeCodePatterns, + bool IncludeGlobals) + : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals, Next.isOutputBinary()), AST(AST), Next(Next) { // Compute the set of contexts in which we will look when we don't have @@ -1387,6 +1468,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, FrontendOpts.ShowMacrosInCodeCompletion = IncludeMacros && CachedCompletionResults.empty(); FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns; + FrontendOpts.ShowGlobalSymbolsInCodeCompletion + = CachedCompletionResults.empty(); FrontendOpts.CodeCompletionAt.FileName = File; FrontendOpts.CodeCompletionAt.Line = Line; FrontendOpts.CodeCompletionAt.Column = Column; @@ -1447,7 +1530,8 @@ void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column, // code-completion results. AugmentedCodeCompleteConsumer AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion, - FrontendOpts.ShowCodePatternsInCodeCompletion); + FrontendOpts.ShowCodePatternsInCodeCompletion, + FrontendOpts.ShowGlobalSymbolsInCodeCompletion); Clang.setCodeCompletionConsumer(&AugmentedConsumer); // If we have a precompiled preamble, try to use it. We only allow diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 06ec80589c..8e1dbcb9d2 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -328,6 +328,7 @@ void CompilerInstance::createCodeCompletionConsumer() { getFrontendOpts().DebugCodeCompletionPrinter, getFrontendOpts().ShowMacrosInCodeCompletion, getFrontendOpts().ShowCodePatternsInCodeCompletion, + getFrontendOpts().ShowGlobalSymbolsInCodeCompletion, llvm::outs())); if (!CompletionConsumer) return; @@ -356,15 +357,18 @@ CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP, bool UseDebugPrinter, bool ShowMacros, bool ShowCodePatterns, + bool ShowGlobals, llvm::raw_ostream &OS) { if (EnableCodeCompletion(PP, Filename, Line, Column)) return 0; // Set up the creation routine for code-completion. if (UseDebugPrinter) - return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS); + return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns, + ShowGlobals, OS); else - return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, OS); + return new CIndexCodeCompleteConsumer(ShowMacros, ShowCodePatterns, + ShowGlobals, OS); } void CompilerInstance::createSema(bool CompleteTranslationUnit, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index aa6888bd1d..5605f16dac 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -363,6 +363,8 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-code-completion-macros"); if (Opts.ShowCodePatternsInCodeCompletion) Res.push_back("-code-completion-patterns"); + if (!Opts.ShowGlobalSymbolsInCodeCompletion) + Res.push_back("-no-code-completion-globals"); if (Opts.ShowStats) Res.push_back("-print-stats"); if (Opts.ShowTimers) @@ -1047,6 +1049,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros); Opts.ShowCodePatternsInCodeCompletion = Args.hasArg(OPT_code_completion_patterns); + Opts.ShowGlobalSymbolsInCodeCompletion + = !Args.hasArg(OPT_no_code_completion_globals); Opts.ShowStats = Args.hasArg(OPT_print_stats); Opts.ShowTimers = Args.hasArg(OPT_ftime_report); Opts.ShowVersion = Args.hasArg(OPT_version); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 31185683a1..599a10fd90 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2308,7 +2308,8 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, } CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.EnterNewScope(); AddOrdinaryNameResults(CompletionContext, S, *this, Results); @@ -2340,7 +2341,8 @@ void Sema::CodeCompleteExpression(Scope *S, QualType T, Results.setPreferredType(T.getNonReferenceType()); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.EnterNewScope(); AddOrdinaryNameResults(PCC_Expression, S, *this, Results); @@ -2432,7 +2434,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, // Access to a C/C++ class, struct, or union. Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer); + LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); if (getLangOptions().CPlusPlus) { if (!Results.empty()) { @@ -2480,7 +2483,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, if (Class) { CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.setFilter(&ResultBuilder::IsObjCIvar); - LookupVisibleDecls(Class, LookupMemberName, Consumer); + LookupVisibleDecls(Class, LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); } } @@ -2530,11 +2534,14 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { // First pass: look for tags. Results.setFilter(Filter); - LookupVisibleDecls(S, LookupTagName, Consumer); + LookupVisibleDecls(S, LookupTagName, Consumer, + CodeCompleter->includeGlobals()); - // Second pass: look for nested name specifiers. - Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + if (CodeCompleter->includeGlobals()) { + // Second pass: look for nested name specifiers. + Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + } HandleCodeCompleteResults(this, CodeCompleter, ContextKind, Results.data(),Results.size()); @@ -2836,7 +2843,8 @@ void Sema::CodeCompleteUsing(Scope *S) { // After "using", we can see anything that would start a // nested-name-specifier. CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, @@ -2853,10 +2861,11 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); Results.EnterNewScope(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, + CodeCompletionContext::CCC_Namespace, Results.data(),Results.size()); } @@ -2903,9 +2912,10 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { // After "namespace", we expect to see a namespace or alias. ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, + CodeCompletionContext::CCC_Namespace, Results.data(),Results.size()); } @@ -2926,14 +2936,15 @@ void Sema::CodeCompleteOperatorName(Scope *S) { // Add any type names visible from the current scope Results.allowNestedNameSpecifiers(); CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); // Add any type specifiers AddTypeSpecifierResults(getLangOptions(), Results); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, - CodeCompletionContext::CCC_Other, + CodeCompletionContext::CCC_Type, Results.data(),Results.size()); } @@ -3514,7 +3525,8 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { Results.setFilter(&ResultBuilder::IsObjCMessageReceiver); CodeCompletionDeclConsumer Consumer(Results, CurContext); Results.EnterNewScope(); - LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); // If we are in an Objective-C method inside a class that has a superclass, // add "super" as an option. @@ -4341,13 +4353,12 @@ void Sema::GatherGlobalCodeCompletions( llvm::SmallVectorImpl<CodeCompleteConsumer::Result> &Results) { ResultBuilder Builder(*this); -#if 0 - // FIXME: We need a name lookup that means "look for everything", - CodeCompletionDeclConsumer Consumer(Builder, - Context.getTranslationUnitDecl()); - LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupOrdinaryName, - Consumer); -#endif + if (!CodeCompleter || CodeCompleter->includeGlobals()) { + CodeCompletionDeclConsumer Consumer(Builder, + Context.getTranslationUnitDecl()); + LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, + Consumer); + } if (!CodeCompleter || CodeCompleter->includeMacros()) AddMacroResults(PP, Builder); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1ffea89acd..994b633db8 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -254,6 +254,12 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind, case Sema::LookupObjCProtocolName: IDNS = Decl::IDNS_ObjCProtocol; break; + + case Sema::LookupAnyName: + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member + | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol + | Decl::IDNS_Type; + break; } return IDNS; } @@ -1199,6 +1205,17 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, return Found; } +/// \brief Callback that looks for any member of a class with the given name. +static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *Name) { + RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); + + DeclarationName N = DeclarationName::getFromOpaquePtr(Name); + Path.Decls = BaseRecord->lookup(N); + return Path.Decls.first != Path.Decls.second; +} + /// \brief Perform qualified name lookup into a given context. /// /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find @@ -1294,6 +1311,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, BaseCallback = &CXXRecordDecl::FindTagMember; break; + case LookupAnyName: + BaseCallback = &LookupAnyMember; + break; + case LookupUsingDeclName: // This lookup is for redeclarations only. @@ -2223,6 +2244,10 @@ public: return !VisitedContexts.insert(Ctx); } + bool alreadyVisitedContext(DeclContext *Ctx) { + return VisitedContexts.count(Ctx); + } + /// \brief Determine whether the given declaration is hidden in the /// current scope. /// @@ -2503,7 +2528,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, if (!S) return; - if (!S->getEntity() || !S->getParent() || + if (!S->getEntity() || + (!S->getParent() && + !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) || ((DeclContext *)S->getEntity())->isFunctionOrMethod()) { // Walk through the declarations in this Scope. for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); @@ -2581,7 +2608,8 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, } void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, - VisibleDeclConsumer &Consumer) { + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { // Determine the set of using directives available during // unqualified name lookup. Scope *Initial = S; @@ -2598,14 +2626,19 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, // Look for visible declarations. LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); VisibleDeclsRecord Visited; + if (!IncludeGlobalScope) + Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited); } void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, - VisibleDeclConsumer &Consumer) { + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); VisibleDeclsRecord Visited; + if (!IncludeGlobalScope) + Visited.visitedContext(Context.getTranslationUnitDecl()); ShadowContextRAII Shadow(Visited); ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, /*InBaseClass=*/false, Consumer, Visited); diff --git a/test/Index/complete-exprs.c b/test/Index/complete-exprs.c index ef19d1484d..7dfe280d9e 100644 --- a/test/Index/complete-exprs.c +++ b/test/Index/complete-exprs.c @@ -19,6 +19,12 @@ const char *str = "Hello, \nWorld"; // CHECK-CC1-NOT: NotImplemented:{TypedText float} (40) // CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2) // CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1a %s +// FIXME: Priorities aren't right +// CHECK-CC1a: ParmDecl:{ResultType int}{TypedText j} (2) +// CHECK-CC1a: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30) +// CHECK-CC1a: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50) +// CHECK-CC1a: macro definition:{TypedText __VERSION__} (70) // RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s // RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: macro definition:{TypedText __VERSION__} (70) diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index f0e90212f7..48bbe7d46b 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -547,7 +547,8 @@ namespace { public: explicit CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results) - : CodeCompleteConsumer(true, false, false), AllocatedResults(Results) { } + : CodeCompleteConsumer(true, false, true, false), + AllocatedResults(Results) { } virtual void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, |