diff options
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 107 |
1 files changed, 76 insertions, 31 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 85596ed52e9d..d3f91a4e273d 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -88,13 +88,15 @@ namespace { /// A collection of using directives, as used by C++ unqualified /// lookup. class UnqualUsingDirectiveSet { + Sema &SemaRef; + typedef SmallVector<UnqualUsingEntry, 8> ListTy; ListTy list; llvm::SmallPtrSet<DeclContext*, 8> visited; public: - UnqualUsingDirectiveSet() {} + UnqualUsingDirectiveSet(Sema &SemaRef) : SemaRef(SemaRef) {} void visitScopeChain(Scope *S, Scope *InnermostFileScope) { // C++ [namespace.udir]p1: @@ -113,7 +115,8 @@ namespace { visit(Ctx, Ctx); } else if (!Ctx || Ctx->isFunctionOrMethod()) { for (auto *I : S->using_directives()) - visit(I, InnermostFileDC); + if (SemaRef.isVisible(I)) + visit(I, InnermostFileDC); } } } @@ -152,7 +155,7 @@ namespace { while (true) { for (auto UD : DC->using_directives()) { DeclContext *NS = UD->getNominatedNamespace(); - if (visited.insert(NS).second) { + if (SemaRef.isVisible(UD) && visited.insert(NS).second) { addUsingDirective(UD, EffectiveDC); queue.push_back(NS); } @@ -1031,7 +1034,8 @@ struct FindLocalExternScope { FindLocalExternScope(LookupResult &R) : R(R), OldFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_LocalExtern) { - R.setFindLocalExtern(R.getIdentifierNamespace() & Decl::IDNS_Ordinary); + R.setFindLocalExtern(R.getIdentifierNamespace() & + (Decl::IDNS_Ordinary | Decl::IDNS_NonMemberOperator)); } void restore() { R.setFindLocalExtern(OldFindLocalExtern); @@ -1084,7 +1088,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // } // } // - UnqualUsingDirectiveSet UDirs; + UnqualUsingDirectiveSet UDirs(*this); bool VisitedUsingDirectives = false; bool LeftStartingScope = false; DeclContext *OutsideOfTemplateParamDC = nullptr; @@ -1370,7 +1374,7 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) { // Walk up to the containing context. That might also have been instantiated // from a template. - DeclContext *Context = Entity->getDeclContext(); + DeclContext *Context = Entity->getLexicalDeclContext(); if (Context->isFileContext()) return S.getOwningModule(Entity); return getDefiningModule(S, cast<Decl>(Context)); @@ -1608,11 +1612,39 @@ bool Sema::isVisibleSlow(const NamedDecl *D) { } bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) { + // FIXME: If there are both visible and hidden declarations, we need to take + // into account whether redeclaration is possible. Example: + // + // Non-imported module: + // int f(T); // #1 + // Some TU: + // static int f(U); // #2, not a redeclaration of #1 + // int f(T); // #3, finds both, should link with #1 if T != U, but + // // with #2 if T == U; neither should be ambiguous. for (auto *D : R) { if (isVisible(D)) return true; + assert(D->isExternallyDeclarable() && + "should not have hidden, non-externally-declarable result here"); } - return New->isExternallyVisible(); + + // This function is called once "New" is essentially complete, but before a + // previous declaration is attached. We can't query the linkage of "New" in + // general, because attaching the previous declaration can change the + // linkage of New to match the previous declaration. + // + // However, because we've just determined that there is no *visible* prior + // declaration, we can compute the linkage here. There are two possibilities: + // + // * This is not a redeclaration; it's safe to compute the linkage now. + // + // * This is a redeclaration of a prior declaration that is externally + // redeclarable. In that case, the linkage of the declaration is not + // changed by attaching the prior declaration, because both are externally + // declarable (and thus ExternalLinkage or VisibleNoLinkage). + // + // FIXME: This is subtle and fragile. + return New->isExternallyDeclarable(); } /// \brief Retrieve the visible declaration corresponding to D, if any. @@ -1839,22 +1871,19 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, DeclContext *StartDC) { assert(StartDC->isFileContext() && "start context is not a file context"); - DeclContext::udir_range UsingDirectives = StartDC->using_directives(); - if (UsingDirectives.begin() == UsingDirectives.end()) return false; + // We have not yet looked into these namespaces, much less added + // their "using-children" to the queue. + SmallVector<NamespaceDecl*, 8> Queue; // We have at least added all these contexts to the queue. llvm::SmallPtrSet<DeclContext*, 8> Visited; Visited.insert(StartDC); - // We have not yet looked into these namespaces, much less added - // their "using-children" to the queue. - SmallVector<NamespaceDecl*, 8> Queue; - // We have already looked into the initial namespace; seed the queue // with its using-children. - for (auto *I : UsingDirectives) { + for (auto *I : StartDC->using_directives()) { NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace(); - if (Visited.insert(ND).second) + if (S.isVisible(I) && Visited.insert(ND).second) Queue.push_back(ND); } @@ -1902,7 +1931,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, for (auto I : ND->using_directives()) { NamespaceDecl *Nom = I->getNominatedNamespace(); - if (Visited.insert(Nom).second) + if (S.isVisible(I) && Visited.insert(Nom).second) Queue.push_back(Nom); } } @@ -3121,7 +3150,7 @@ Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, bool AllowRaw, bool AllowTemplate, - bool AllowStringTemplate) { + bool AllowStringTemplate, bool DiagnoseMissing) { LookupName(R, S); assert(R.getResultKind() != LookupResult::Ambiguous && "literal operator lookup can't be ambiguous"); @@ -3222,11 +3251,15 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, return LOLR_StringTemplate; // Didn't find anything we could use. - Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) - << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] - << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw - << (AllowTemplate || AllowStringTemplate); - return LOLR_Error; + if (DiagnoseMissing) { + Diag(R.getNameLoc(), diag::err_ovl_no_viable_literal_operator) + << R.getLookupName() << (int)ArgTys.size() << ArgTys[0] + << (ArgTys.size() == 2 ? ArgTys[1] : QualType()) << AllowRaw + << (AllowTemplate || AllowStringTemplate); + return LOLR_Error; + } + + return LOLR_ErrorNoDiagnostic; } void ADLResult::insert(NamedDecl *New) { @@ -3316,16 +3349,24 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, continue; } - if (isa<UsingShadowDecl>(D)) - D = cast<UsingShadowDecl>(D)->getTargetDecl(); + auto *Underlying = D; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); - if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) + if (!isa<FunctionDecl>(Underlying) && + !isa<FunctionTemplateDecl>(Underlying)) continue; - if (!isVisible(D) && !(D = findAcceptableDecl(*this, D))) - continue; + if (!isVisible(D)) { + D = findAcceptableDecl(*this, D); + if (!D) + continue; + if (auto *USD = dyn_cast<UsingShadowDecl>(D)) + Underlying = USD->getTargetDecl(); + } - Result.insert(D); + // FIXME: Preserve D as the FoundDecl. + Result.insert(Underlying); } } } @@ -3507,6 +3548,8 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, if (QualifiedNameLookup) { ShadowContextRAII Shadow(Visited); for (auto I : Ctx->using_directives()) { + if (!Result.getSema().isVisible(I)) + continue; LookupVisibleDecls(I->getNominatedNamespace(), Result, QualifiedNameLookup, InBaseClass, Consumer, Visited, IncludeDependentBases); @@ -3634,8 +3677,10 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, !Visited.alreadyVisitedContext(S->getEntity())) || (S->getEntity())->isFunctionOrMethod()) { FindLocalExternScope FindLocals(Result); - // Walk through the declarations in this Scope. - for (auto *D : S->decls()) { + // Walk through the declarations in this Scope. The consumer might add new + // decls to the scope as part of deserialization, so make a copy first. + SmallVector<Decl *, 8> ScopeDecls(S->decls().begin(), S->decls().end()); + for (Decl *D : ScopeDecls) { if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), nullptr, false); @@ -3713,7 +3758,7 @@ void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, // Determine the set of using directives available during // unqualified name lookup. Scope *Initial = S; - UnqualUsingDirectiveSet UDirs; + UnqualUsingDirectiveSet UDirs(*this); if (getLangOpts().CPlusPlus) { // Find the first namespace or translation-unit scope. while (S && !isNamespaceOrTranslationUnitScope(S)) |