aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Frontend/ASTUnit.cpp96
-rw-r--r--lib/Frontend/CompilerInstance.cpp8
-rw-r--r--lib/Frontend/CompilerInvocation.cpp4
-rw-r--r--lib/Sema/SemaCodeComplete.cpp57
-rw-r--r--lib/Sema/SemaLookup.cpp39
5 files changed, 170 insertions, 34 deletions
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);