return Paths;
}
- /// \brief Tests whether the given declaration is acceptable.
- bool isAcceptableDecl(NamedDecl *D) const {
- if (!D->isInIdentifierNamespace(IDNS))
- return false;
-
+ /// \brief Determine whether the given declaration is visible to the
+ /// program.
+ static bool isVisible(NamedDecl *D) {
// So long as this declaration is not module-private or was parsed as
- // part of this translation unit (i.e., in the module), we're allowed to
- // find it.
+ // part of this translation unit (i.e., in the module), it's visible.
if (!D->isModulePrivate() || !D->isFromASTFile())
return true;
-
+
// FIXME: We should be allowed to refer to a module-private name from
// within the same module, e.g., during template instantiation.
// This requires us know which module a particular declaration came from.
return false;
}
-
+
+ /// \brief Retrieve the accepted (re)declaration of the given declaration,
+ /// if there is one.
+ NamedDecl *getAcceptableDecl(NamedDecl *D) const {
+ if (!D->isInIdentifierNamespace(IDNS))
+ return 0;
+
+ if (isVisible(D))
+ return D;
+
+ return getAcceptableDeclSlow(D);
+ }
+
+private:
+ NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
+public:
+
/// \brief Returns the identifier namespace mask for this lookup.
unsigned getIdentifierNamespace() const {
return IDNS;
delete Paths;
}
+static NamedDecl *getVisibleDecl(NamedDecl *D);
+
+NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
+ return getVisibleDecl(D);
+}
+
/// Resolves the result kind of this lookup.
void LookupResult::resolveKind() {
unsigned N = Decls.size();
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
NamedDecl *D = *I;
- if (R.isAcceptableDecl(D)) {
+ if ((D = R.getAcceptableDecl(D))) {
R.addDecl(D);
Found = true;
}
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(*I); ++I) {
- if (R.isAcceptableDecl(*I)) {
+ if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
Found = true;
- R.addDecl(*I);
+ R.addDecl(ND);
}
}
if (Found) {
if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(
Name.getAsIdentifierInfo(),
ClassDeclared)) {
- if (R.isAcceptableDecl(Ivar)) {
- R.addDecl(Ivar);
+ if (NamedDecl *ND = R.getAcceptableDecl(Ivar)) {
+ R.addDecl(ND);
R.resolveKind();
return true;
}
// Check whether the IdResolver has anything in this scope.
bool Found = false;
for (; I != IEnd && S->isDeclScope(*I); ++I) {
- if (R.isAcceptableDecl(*I)) {
+ if (NamedDecl *ND = R.getAcceptableDecl(*I)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
// namespace, so that we can construct an overload set if we
// need to.
Found = true;
- R.addDecl(*I);
+ R.addDecl(ND);
}
}
return !R.empty();
}
+/// \brief Retrieve the previous declaration of D.
+static NamedDecl *getPreviousDeclaration(NamedDecl *D) {
+ if (TagDecl *TD = dyn_cast<TagDecl>(D))
+ return TD->getPreviousDeclaration();
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ return VD->getPreviousDeclaration();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ return FD->getPreviousDeclaration();
+ if (RedeclarableTemplateDecl *RTD = dyn_cast<RedeclarableTemplateDecl>(D))
+ return RTD->getPreviousDeclaration();
+
+ return 0;
+}
+
+/// \brief Retrieve the visible declaration corresponding to D, if any.
+///
+/// This routine determines whether the declaration D is visible in the current
+/// module, with the current imports. If not, it checks whether any
+/// redeclaration of D is visible, and if so, returns that declaration.
+///
+/// \returns D, or a visible previous declaration of D, whichever is more recent
+/// and visible. If no declaration of D is visible, returns null.
+static NamedDecl *getVisibleDecl(NamedDecl *D) {
+ if (LookupResult::isVisible(D))
+ return D;
+
+ while ((D = getPreviousDeclaration(D))) {
+ if (LookupResult::isVisible(D))
+ return D;
+ }
+
+ return 0;
+}
+
/// @brief Perform unqualified name lookup starting from a given
/// scope.
///
// If this declaration is module-private and it came from an AST
// file, we can't see it.
- if ((*I)->isModulePrivate() && (*I)->isFromASTFile())
+ NamedDecl *D = getVisibleDecl(*I);
+ if (!D)
continue;
-
- R.addDecl(*I);
+
+ R.addDecl(D);
if ((*I)->getAttr<OverloadableAttr>()) {
// If this declaration has the "overloadable" attribute, we
for (++LastI; LastI != IEnd; ++LastI) {
if (!S->isDeclScope(*LastI))
break;
- R.addDecl(*LastI);
+
+ D = getVisibleDecl(*LastI);
+ if (D)
+ R.addDecl(D);
}
}
DEnd = CurCtx->decls_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
- if (Result.isAcceptableDecl(ND)) {
+ if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
Visited.add(ND);
}
PEnd = ForwardProto->protocol_end();
P != PEnd;
++P) {
- if (Result.isAcceptableDecl(*P)) {
- Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass);
- Visited.add(*P);
+ if (NamedDecl *ND = Result.getAcceptableDecl(*P)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
}
}
} else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
- if (Result.isAcceptableDecl(IFace)) {
- Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx,
- InBaseClass);
- Visited.add(IFace);
+ if (NamedDecl *ND = Result.getAcceptableDecl(IFace)) {
+ Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
+ Visited.add(ND);
}
}
for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
- if (Result.isAcceptableDecl(ND)) {
+ if ((ND = Result.getAcceptableDecl(ND))) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
Visited.add(ND);
}