aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp144
1 files changed, 38 insertions, 106 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index fe12eb74b9..53174b68a1 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2308,42 +2308,6 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
}
-/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is
-/// an acceptable non-member overloaded operator for a call whose
-/// arguments have types T1 (and, if non-empty, T2). This routine
-/// implements the check in C++ [over.match.oper]p3b2 concerning
-/// enumeration types.
-static bool
-IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn,
- QualType T1, QualType T2,
- ASTContext &Context) {
- if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
- return true;
-
- const FunctionProtoType *Proto = Fn->getType()->getAsFunctionProtoType();
- if (Proto->getNumArgs() < 1)
- return false;
-
- if (T1->isEnumeralType()) {
- QualType ArgType = Proto->getArgType(0).getNonReferenceType();
- if (Context.getCanonicalType(T1).getUnqualifiedType()
- == Context.getCanonicalType(ArgType).getUnqualifiedType())
- return true;
- }
-
- if (Proto->getNumArgs() < 2)
- return false;
-
- if (!T2.isNull() && T2->isEnumeralType()) {
- QualType ArgType = Proto->getArgType(1).getNonReferenceType();
- if (Context.getCanonicalType(T2).getUnqualifiedType()
- == Context.getCanonicalType(ArgType).getUnqualifiedType())
- return true;
- }
-
- return false;
-}
-
/// AddOperatorCandidates - Add the overloaded operator candidates for
/// the operator Op that was used in an operator expression such as "x
/// Op y". S is the scope in which the expression occurred (used for
@@ -2383,6 +2347,8 @@ bool Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
/*SuppressUserConversions=*/false);
}
+ FunctionSet Functions;
+
// -- The set of non-member candidates is the result of the
// unqualified lookup of operator@ in the context of the
// expression according to the usual rules for name lookup in
@@ -2394,24 +2360,19 @@ bool Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
// type, or (if there is a right operand) a second parameter
// of type T2 or “reference to (possibly cv-qualified) T2”,
// when T2 is an enumeration type, are candidate functions.
- LookupResult Operators = LookupName(S, OpName, LookupOperatorName);
-
- if (Operators.isAmbiguous())
- return DiagnoseAmbiguousLookup(Operators, OpName, OpLoc, OpRange);
- else if (Operators) {
- for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
- Op != OpEnd; ++Op) {
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op))
- if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
- AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
- /*SuppressUserConversions=*/false);
- }
- }
+ LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
// Since the set of non-member candidates corresponds to
// *unqualified* lookup of the operator name, we also perform
// argument-dependent lookup (C++ [basic.lookup.argdep]).
- AddArgumentDependentLookupCandidates(OpName, Args, NumArgs, CandidateSet);
+ ArgumentDependentLookup(OpName, Args, NumArgs, Functions);
+
+ // Add all of the functions found via operator name lookup and
+ // argument-dependent lookup to the candidate set.
+ for (FunctionSet::iterator Func = Functions.begin(),
+ FuncEnd = Functions.end();
+ Func != FuncEnd; ++Func)
+ AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
// Add builtin overload candidates (C++ [over.built]).
AddBuiltinOperatorCandidates(Op, Args, NumArgs, CandidateSet);
@@ -3250,62 +3211,33 @@ 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);
- }
- }
+ FunctionSet Functions;
+
+ // 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)
+ if (Cand->Function)
+ Functions.insert(Cand->Function);
+
+ ArgumentDependentLookup(Name, Args, NumArgs, Functions);
+
+ // Erase all of the candidates we already knew about.
+ // FIXME: This is suboptimal. Is there a better way?
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+ CandEnd = CandidateSet.end();
+ Cand != CandEnd; ++Cand)
+ if (Cand->Function)
+ Functions.erase(Cand->Function);
+
+ // For each of the ADL candidates we found, add it to the overload
+ // set.
+ for (FunctionSet::iterator Func = Functions.begin(),
+ FuncEnd = Functions.end();
+ Func != FuncEnd; ++Func)
+ AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
}
/// isBetterOverloadCandidate - Determines whether the first overload