diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-04 00:32:51 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-04 00:32:51 +0000 |
commit | fa047648b2a5502d7eef117adb4777eb9a63baa6 (patch) | |
tree | f470574705d472f3994b8d1b10eed39b3b478fb7 /lib/Sema/SemaOverload.cpp | |
parent | 4655112d1c64a098c5f7d665175063f4664a7cf6 (diff) |
Initial implementation of argument dependent lookup (a.k.a. ADL,
a.k.a. Koenig lookup) in C++. Most of the pieces are in place, but for
two:
- In an unqualified call g(x), even if the name does not refer to
anything in the current scope, we can still find functions named
"g" based on ADL. We don't yet have this ability.
- ADL will need updating for friend functions and templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63692 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 105 |
1 files changed, 96 insertions, 9 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7219f19a97..293e9c3c24 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2301,6 +2301,9 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, // of type T2 or “reference to (possibly cv-qualified) T2”, // when T2 is an enumeration type, are candidate functions. { + // FIXME: Don't use the IdentifierResolver here! We need to + // perform proper, unqualified lookup starting with the first + // enclosing non-class scope. IdentifierResolver::iterator I = IdResolver.begin(OpName), IEnd = IdResolver.end(); for (; I != IEnd; ++I) { @@ -2327,6 +2330,11 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, /*SuppressUserConversions=*/false); } } + + // Since the set of non-member candidates corresponds to + // *unqualified* lookup of the operator name, we also perform + // argument-dependent lookup. + AddArgumentDependentLookupCandidates(OpName, Args, NumArgs, CandidateSet); } // Add builtin overload candidates (C++ [over.built]). @@ -3153,6 +3161,75 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, } } +/// \brief Add function candidates found via argument-dependent lookup +/// to the set of overloading candidates. +/// +/// This routine performs argument-dependent name lookup based on the +/// given function name (which may also be an operator name) and adds +/// all of the overload candidates found by ADL to the overload +/// candidate set (C++ [basic.lookup.argdep]). +void +Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet) { + // Find all of the associated namespaces and classes based on the + // arguments we have. + AssociatedNamespaceSet AssociatedNamespaces; + AssociatedClassSet AssociatedClasses; + FindAssociatedClassesAndNamespaces(Args, NumArgs, + AssociatedNamespaces, AssociatedClasses); + + // C++ [basic.lookup.argdep]p3: + // + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains [...] then Y is + // empty. Otherwise Y is the set of declarations found in the + // namespaces associated with the argument types as described + // below. The set of declarations found by the lookup of the name + // is the union of X and Y. + // + // Here, we compute Y and add its members to the overloaded + // candidate set. + llvm::SmallPtrSet<FunctionDecl *, 16> KnownCandidates; + for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(), + NSEnd = AssociatedNamespaces.end(); + NS != NSEnd; ++NS) { + // When considering an associated namespace, the lookup is the + // same as the lookup performed when the associated namespace is + // used as a qualifier (3.4.3.2) except that: + // + // -- Any using-directives in the associated namespace are + // ignored. + // + // -- FIXME: Any namespace-scope friend functions declared in + // associated classes are visible within their respective + // namespaces even if they are not visible during an ordinary + // lookup (11.4). + DeclContext::lookup_iterator I, E; + for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) { + FunctionDecl *Func = dyn_cast<FunctionDecl>(*I); + if (!Func) + break; + + if (KnownCandidates.empty()) { + // Record all of the function candidates that we've already + // added to the overload set, so that we don't add those same + // candidates a second time. + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), + CandEnd = CandidateSet.end(); + Cand != CandEnd; ++Cand) + KnownCandidates.insert(Cand->Function); + } + + // If we haven't seen this function before, add it as a + // candidate. + if (KnownCandidates.insert(Func)) + AddOverloadCandidate(Func, Args, NumArgs, CandidateSet); + } + } +} + /// AddOverloadCandidates - Add all of the function overloads in Ovl /// to the candidate set. void @@ -3419,19 +3496,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, } /// ResolveOverloadedCallFn - Given the call expression that calls Fn -/// (which eventually refers to the set of overloaded functions in -/// Ovl) and the call arguments Args/NumArgs, attempt to resolve the -/// function call down to a specific function. If overload resolution -/// succeeds, returns the function declaration produced by overload +/// (which eventually refers to the declaration Func) and the call +/// arguments Args/NumArgs, attempt to resolve the function call down +/// to a specific function. If overload resolution succeeds, returns +/// the function declaration produced by overload /// resolution. Otherwise, emits diagnostics, deletes all of the /// arguments and Fn, and returns NULL. -FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, OverloadedFunctionDecl *Ovl, +FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + bool ArgumentDependentLookup) { OverloadCandidateSet CandidateSet; - AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet); + if (OverloadedFunctionDecl *Ovl + = dyn_cast_or_null<OverloadedFunctionDecl>(Callee)) + AddOverloadCandidates(Ovl, Args, NumArgs, CandidateSet); + else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) + AddOverloadCandidate(cast<FunctionDecl>(Func), Args, NumArgs, CandidateSet); + + if (ArgumentDependentLookup) + AddArgumentDependentLookupCandidates(Callee->getDeclName(), Args, NumArgs, + CandidateSet); + OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Best)) { case OR_Success: @@ -3440,14 +3527,14 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, OverloadedFunctionDecl *Ov case OR_No_Viable_Function: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_no_viable_function_in_call) - << Ovl->getDeclName() << (unsigned)CandidateSet.size() + << Callee->getDeclName() << (unsigned)CandidateSet.size() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); break; case OR_Ambiguous: Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) - << Ovl->getDeclName() << Fn->getSourceRange(); + << Callee->getDeclName() << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; } |