From: Eric Liu Date: Wed, 13 Dec 2017 10:26:49 +0000 (+0000) Subject: [Sema] Ignore decls in namespaces when global decls are not wanted. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=979ce58814f6d861f8a9a4da08932916bafd38d9;p=clang [Sema] Ignore decls in namespaces when global decls are not wanted. Summary: ... in qualified code completion and decl lookup. Reviewers: ilya-biryukov, arphaman Reviewed By: ilya-biryukov Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D40562 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@320563 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 4f980c202b..c81fbfd9d5 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -437,6 +437,8 @@ 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 no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level-decls">, + HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">; def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">, HelpText<"Include brief documentation comments in code-completion results.">; def disable_free : Flag<["-"], "disable-free">, diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index fb09b99bbd..5d280b5608 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -919,8 +919,13 @@ public: } /// \brief Whether to include global (top-level) declaration results. - bool includeGlobals() const { - return CodeCompleteOpts.IncludeGlobals; + bool includeGlobals() const { return CodeCompleteOpts.IncludeGlobals; } + + /// \brief Whether to include declarations in namespace contexts (including + /// the global namespace). If this is false, `includeGlobals()` will be + /// ignored. + bool includeNamespaceLevelDecls() const { + return CodeCompleteOpts.IncludeNamespaceLevelDecls; } /// \brief Whether to include brief documentation comments within the set of diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h index fc7713c795..091d8ca605 100644 --- a/include/clang/Sema/CodeCompleteOptions.h +++ b/include/clang/Sema/CodeCompleteOptions.h @@ -24,15 +24,20 @@ public: /// Show top-level decls in code completion results. unsigned IncludeGlobals : 1; + /// Show decls in namespace (including the global namespace) in code + /// completion results. If this is 0, `IncludeGlobals` will be ignored. + /// + /// Currently, this only works when completing qualified IDs (i.e. + /// `Sema::CodeCompleteQualifiedId`). + /// FIXME: consider supporting more completion cases with this option. + unsigned IncludeNamespaceLevelDecls : 1; + /// Show brief documentation comments in code completion results. unsigned IncludeBriefComments : 1; - CodeCompleteOptions() : - IncludeMacros(0), - IncludeCodePatterns(0), - IncludeGlobals(1), - IncludeBriefComments(0) - { } + CodeCompleteOptions() + : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1), + IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {} }; } // namespace clang diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3aa615b490..be907d9ba8 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1380,6 +1380,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, = Args.hasArg(OPT_code_completion_patterns); Opts.CodeCompleteOpts.IncludeGlobals = !Args.hasArg(OPT_no_code_completion_globals); + Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls + = !Args.hasArg(OPT_no_code_completion_ns_level_decls); Opts.CodeCompleteOpts.IncludeBriefComments = Args.hasArg(OPT_code_completion_brief_comments); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3dd3c9f59e..ee11c5c94e 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -4647,10 +4647,13 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, MaybeAddOverrideCalls(*this, Ctx, Results); Results.ExitScope(); - CodeCompletionDeclConsumer Consumer(Results, CurContext); - LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, - /*IncludeGlobalScope=*/true, - /*IncludeDependentBases=*/true); + if (CodeCompleter->includeNamespaceLevelDecls() || + (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) { + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, + /*IncludeGlobalScope=*/true, + /*IncludeDependentBases=*/true); + } auto CC = Results.getCompletionContext(); CC.setCXXScopeSpecifier(SS); diff --git a/test/CodeCompletion/ignore-ns-level-decls.cpp b/test/CodeCompletion/ignore-ns-level-decls.cpp new file mode 100644 index 0000000000..59cee6536a --- /dev/null +++ b/test/CodeCompletion/ignore-ns-level-decls.cpp @@ -0,0 +1,21 @@ +namespace ns { + struct bar { + }; + + struct baz { + }; + + int func(int a, bar b, baz c); +} + +void test() { + ns:: +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:12:7 %s -o - | FileCheck %s --check-prefix=CHECK-1 +// CHECK-1-DAG: COMPLETION: bar : bar +// CHECK-1-DAG: COMPLETION: baz : baz +// CHECK-1-DAG: COMPLETION: func : [#int#]func(<#int a#>, <#bar b#>, <#baz c#>) + +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:12:7 -no-code-completion-ns-level-decls %s -o - | FileCheck %s --allow-empty --check-prefix=CHECK-EMPTY +// CHECK-EMPTY-NOT: COMPLETION: bar : bar +// CHECK-EMPTY: {{^}}{{$}} +}