diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-04-17 01:52:14 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-04-17 01:52:14 +0000 |
commit | 13e47c43584d00bb656d62c2125ba5b1ebbbf1f2 (patch) | |
tree | cc969be6ade7e2a7e9ecb098b637cc9438c3ecbd /lib/Sema/SemaLookup.cpp | |
parent | 49c8dad960b99faa2f1f14566317b4e3d2cb7b0a (diff) |
Implement [over.match.oper]p3 properly, by filtering the non-candidates out
when building the candidate set, rather than trying to contort name lookup into
handling this.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206436 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLookup.cpp')
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 90 |
1 files changed, 6 insertions, 84 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index ba9bcd6561..779d2d48e7 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2311,43 +2311,6 @@ void Sema::FindAssociatedClassesAndNamespaces( } } -/// 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->isDependentType() || (!T2.isNull() && T2->isDependentType())) - return true; - - if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) - return true; - - const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>(); - if (Proto->getNumParams() < 1) - return false; - - if (T1->isEnumeralType()) { - QualType ArgType = Proto->getParamType(0).getNonReferenceType(); - if (Context.hasSameUnqualifiedType(T1, ArgType)) - return true; - } - - if (Proto->getNumParams() < 2) - return false; - - if (!T2.isNull() && T2->isEnumeralType()) { - QualType ArgType = Proto->getParamType(1).getNonReferenceType(); - if (Context.hasSameUnqualifiedType(T2, ArgType)) - return true; - } - - return false; -} - NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, @@ -2374,41 +2337,13 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, // unqualified lookup of operator@ in the context of the // expression according to the usual rules for name lookup in // unqualified function calls (3.4.2) except that all member - // functions are ignored. However, if no operand has a class - // type, only those non-member functions in the lookup set - // that have a first parameter of type T1 or "reference to - // (possibly cv-qualified) T1", when T1 is an enumeration - // 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. + // functions are ignored. DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName); LookupName(Operators, S); assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); - - if (Operators.empty()) - return; - - for (auto I = Operators.begin(), E = Operators.end(); I != E; ++I) - addOverloadedOperatorToUnresolvedSet(Functions, I.getPair(), T1, T2); -} - -void Sema::addOverloadedOperatorToUnresolvedSet(UnresolvedSetImpl &Functions, - DeclAccessPair Op, - QualType T1, QualType T2) { - NamedDecl *Found = Op->getUnderlyingDecl(); - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) { - if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) - Functions.addDecl(Op, Op.getAccess()); // FIXME: canonical FD - } else if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(Found)) { - // FIXME: friend operators? - // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, - // later? - if (!FunTmpl->getDeclContext()->isRecord()) - Functions.addDecl(Op, Op.getAccess()); - } + Functions.append(Operators.begin(), Operators.end()); } Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, @@ -2529,7 +2464,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, // Now we perform lookup on the name we computed earlier and do overload // resolution. Lookup is only performed directly into the class since there // will always be a (possibly implicit) declaration to shadow any others. - OverloadCandidateSet OCS(RD->getLocation()); + OverloadCandidateSet OCS(RD->getLocation(), OverloadCandidateSet::CSK_Normal); DeclContext::lookup_result R = RD->lookup(Name); assert(!R.empty() && "lookup for a constructor or assignment operator was empty"); @@ -2849,9 +2784,8 @@ void ADLResult::insert(NamedDecl *New) { Old = New; } -void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, - SourceLocation Loc, ArrayRef<Expr *> Args, - ADLResult &Result) { +void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, + ArrayRef<Expr *> Args, ADLResult &Result) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; @@ -2860,13 +2794,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, AssociatedNamespaces, AssociatedClasses); - QualType T1, T2; - if (Operator) { - T1 = Args[0]->getType(); - if (Args.size() >= 2) - T2 = Args[1]->getType(); - } - // 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 @@ -2919,12 +2846,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); - if (isa<FunctionDecl>(D)) { - if (Operator && - !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D), - T1, T2, Context)) - continue; - } else if (!isa<FunctionTemplateDecl>(D)) + if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) continue; Result.insert(D); |