diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp | 112 | 
1 files changed, 79 insertions, 33 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 85596ed52e9d..a9db973851df 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/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)); @@ -1585,7 +1589,7 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {      return false;    // Find the extra places where we need to look. -  llvm::DenseSet<Module*> &LookupModules = SemaRef.getLookupModules(); +  const auto &LookupModules = SemaRef.getLookupModules();    if (LookupModules.empty())      return false; @@ -1600,7 +1604,8 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, NamedDecl *D) {    // Check whether DeclModule is transitively exported to an import of    // the lookup set.    return std::any_of(LookupModules.begin(), LookupModules.end(), -                     [&](Module *M) { return M->isModuleVisible(DeclModule); }); +                     [&](const Module *M) { +                       return M->isModuleVisible(DeclModule); });  }  bool Sema::isVisibleSlow(const NamedDecl *D) { @@ -1608,11 +1613,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 +1872,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 +1932,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 +3151,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 +3252,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 +3350,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 +3549,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 +3678,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 +3759,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))  | 
