aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaCodeComplete.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-01-14 03:21:49 +0000
committerDouglas Gregor <dgregor@apple.com>2010-01-14 03:21:49 +0000
commit45bcd43e34b07958b0a72dad6584fdacf6a11c3c (patch)
treed958c33a6841992d8a375cac8dd098936807f28f /lib/Sema/SemaCodeComplete.cpp
parentb64cc58087b0874ed96ac76ebcf8d9006bd63282 (diff)
Simplify the code-completion logic for nested-name-specifiers: rather
than traversing visible declarations twice, only perform one traversal and recognize nested-name-specifiers as special. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93418 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
-rw-r--r--lib/Sema/SemaCodeComplete.cpp74
1 files changed, 43 insertions, 31 deletions
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 84f92cef26..ade43461a7 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -112,14 +112,18 @@ namespace {
/// \brief If non-NULL, a filter function used to remove any code-completion
/// results that are not desirable.
LookupFilter Filter;
-
+
+ /// \brief Whether we should allow declarations as
+ /// nested-name-specifiers that would otherwise be filtered out.
+ bool AllowNestedNameSpecifiers;
+
/// \brief A list of shadow maps, which is used to model name hiding at
/// different levels of, e.g., the inheritance hierarchy.
std::list<ShadowMap> ShadowMaps;
public:
explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0)
- : SemaRef(SemaRef), Filter(Filter) { }
+ : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { }
/// \brief Set the filter used for code-completion results.
void setFilter(LookupFilter Filter) {
@@ -134,9 +138,19 @@ namespace {
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
+ /// \brief Specify whether nested-name-specifiers are allowed.
+ void allowNestedNameSpecifiers(bool Allow = true) {
+ AllowNestedNameSpecifiers = Allow;
+ }
+
/// \brief Determine whether the given declaration is at all interesting
/// as a code-completion result.
- bool isInterestingDecl(NamedDecl *ND) const;
+ ///
+ /// \param ND the declaration that we are inspecting.
+ ///
+ /// \param AsNestedNameSpecifier will be set true if this declaration is
+ /// only interesting when it is a nested-name-specifier.
+ bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
/// \brief Check whether the result is hidden by the Hiding declaration.
///
@@ -330,7 +344,10 @@ getRequiredQualification(ASTContext &Context,
return Result;
}
-bool ResultBuilder::isInterestingDecl(NamedDecl *ND) const {
+bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
+ bool &AsNestedNameSpecifier) const {
+ AsNestedNameSpecifier = false;
+
ND = ND->getUnderlyingDecl();
unsigned IDNS = ND->getIdentifierNamespace();
@@ -376,8 +393,19 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND) const {
return false;
// Filter out any unwanted results.
- if (Filter && !(this->*Filter)(ND))
+ if (Filter && !(this->*Filter)(ND)) {
+ // Check whether it is interesting as a nested-name-specifier.
+ if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
+ IsNestedNameSpecifier(ND) &&
+ (Filter != &ResultBuilder::IsMember ||
+ (isa<CXXRecordDecl>(ND) &&
+ cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
+ AsNestedNameSpecifier = true;
+ return true;
+ }
+
return false;
+ }
// ... then it must be interesting!
return true;
@@ -429,7 +457,8 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
Decl *CanonDecl = R.Declaration->getCanonicalDecl();
unsigned IDNS = CanonDecl->getIdentifierNamespace();
- if (!isInterestingDecl(R.Declaration))
+ bool AsNestedNameSpecifier = false;
+ if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
ShadowMap &SMap = ShadowMaps.back();
@@ -491,10 +520,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
- if ((Filter == &ResultBuilder::IsNestedNameSpecifier) ||
- (Filter == &ResultBuilder::IsMember &&
- isa<CXXRecordDecl>(R.Declaration) &&
- cast<CXXRecordDecl>(R.Declaration)->isInjectedClassName()))
+ if (AsNestedNameSpecifier)
R.StartsNestedNameSpecifier = true;
// If this result is supposed to have an informative qualifier, add one.
@@ -527,7 +553,8 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
return;
}
- if (!isInterestingDecl(R.Declaration))
+ bool AsNestedNameSpecifier = false;
+ if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
@@ -539,10 +566,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
- if ((Filter == &ResultBuilder::IsNestedNameSpecifier) ||
- (Filter == &ResultBuilder::IsMember &&
- isa<CXXRecordDecl>(R.Declaration) &&
- cast<CXXRecordDecl>(R.Declaration)->isInjectedClassName()))
+ if (AsNestedNameSpecifier)
R.StartsNestedNameSpecifier = true;
// If this result is supposed to have an informative qualifier, add one.
@@ -553,7 +577,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
- SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
+ SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
@@ -664,9 +688,6 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const {
if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
ND = Using->getTargetDecl();
- if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND))
- return Record->isInjectedClassName();
-
return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
isa<ObjCPropertyDecl>(ND);
}
@@ -2132,6 +2153,7 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
Results.EnterNewScope();
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
// Access to a C/C++ class, struct, or union.
+ Results.allowNestedNameSpecifiers();
CollectMemberLookupResults(Record->getDecl(), Record->getDecl(), Results);
if (getLangOptions().CPlusPlus) {
@@ -2223,16 +2245,9 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
}
ResultBuilder Results(*this, Filter);
+ Results.allowNestedNameSpecifiers();
CollectLookupResults(S, Context.getTranslationUnitDecl(), CurContext,Results);
- if (getLangOptions().CPlusPlus) {
- // We could have the start of a nested-name-specifier. Add those
- // results as well.
- Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), CurContext,
- Results);
- }
-
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results);
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
@@ -2518,14 +2533,11 @@ void Sema::CodeCompleteOperatorName(Scope *S) {
#include "clang/Basic/OperatorKinds.def"
// Add any type names visible from the current scope
+ Results.allowNestedNameSpecifiers();
CollectLookupResults(S, Context.getTranslationUnitDecl(), CurContext,Results);
// Add any type specifiers
AddTypeSpecifierResults(getLangOptions(), Results);
-
- // Add any nested-name-specifiers
- Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), CurContext,Results);
Results.ExitScope();
if (CodeCompleter->includeMacros())