From: Richard Smith Date: Thu, 17 Apr 2014 01:52:14 +0000 (+0000) Subject: Implement [over.match.oper]p3 properly, by filtering the non-candidates out X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=13e47c43584d00bb656d62c2125ba5b1ebbbf1f2;p=clang 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 --- diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 7086b723d4..83d8677d9b 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -684,6 +684,18 @@ namespace clang { /// OverloadCandidateSet - A set of overload candidates, used in C++ /// overload resolution (C++ 13.3). class OverloadCandidateSet { + public: + enum CandidateSetKind { + /// Normal lookup. + CSK_Normal, + /// Lookup for candidates for a call using operator syntax. Candidates + /// that have no parameters of class type will be skipped unless there + /// is a parameter of (reference to) enum type and the corresponding + /// argument is of the same enum type. + CSK_Operator + }; + + private: SmallVector Candidates; llvm::SmallPtrSet Functions; @@ -692,6 +704,7 @@ namespace clang { llvm::BumpPtrAllocator ConversionSequenceAllocator; SourceLocation Loc; + CandidateSetKind Kind; unsigned NumInlineSequences; char InlineSpace[16 * sizeof(ImplicitConversionSequence)]; @@ -702,10 +715,12 @@ namespace clang { void destroyCandidates(); public: - OverloadCandidateSet(SourceLocation Loc) : Loc(Loc), NumInlineSequences(0){} + OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK) + : Loc(Loc), Kind(CSK), NumInlineSequences(0) {} ~OverloadCandidateSet() { destroyCandidates(); } SourceLocation getLocation() const { return Loc; } + CandidateSetKind getKind() const { return Kind; } /// \brief Determine when this overload candidate will be new to the /// overload set. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 2b48155abc..7ed7e8b895 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2277,7 +2277,7 @@ public: SourceLocation OpLoc, ArrayRef Args, OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, - bool Operator, SourceLocation Loc, + SourceLocation Loc, ArrayRef Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, @@ -2591,10 +2591,8 @@ public: bool AllowStringTemplate); bool isKnownName(StringRef name); - void ArgumentDependentLookup(DeclarationName Name, bool Operator, - SourceLocation Loc, - ArrayRef Args, - ADLResult &Functions); + void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, + ArrayRef Args, ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 38f7967f9f..4b23c37a63 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3833,7 +3833,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef Args) { // Build an overload candidate set based on the functions we find. SourceLocation Loc = Fn->getExprLoc(); - OverloadCandidateSet CandidateSet(Loc); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); // FIXME: What if we're calling something that isn't a function declaration? // FIXME: What if we're calling a pseudo-destructor? diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index db31ad0cd0..a38c7c1ef8 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1854,7 +1854,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, NamedDecl *ND = Corrected.getCorrectionDecl(); if (ND) { if (Corrected.isOverloaded()) { - OverloadCandidateSet OCS(R.getNameLoc()); + OverloadCandidateSet OCS(R.getNameLoc(), + OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; for (TypoCorrection::decl_iterator CD = Corrected.begin(), CDEnd = Corrected.end(); @@ -4006,7 +4007,7 @@ static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn, S.getScopeForContext(S.CurContext), NULL, CCC)) { if (NamedDecl *ND = Corrected.getCorrectionDecl()) { if (Corrected.isOverloaded()) { - OverloadCandidateSet OCS(NameLoc); + OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; for (TypoCorrection::decl_iterator CD = Corrected.begin(), CDEnd = Corrected.end(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index e3bb944917..81fabd4b20 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1853,7 +1853,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, R.suppressDiagnostics(); - OverloadCandidateSet Candidates(StartLoc); + OverloadCandidateSet Candidates(StartLoc, OverloadCandidateSet::CSK_Normal); for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); Alloc != AllocEnd; ++Alloc) { // Even member operator new/delete are implicitly treated as @@ -4303,7 +4303,8 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc) { Expr *Args[2] = { LHS.get(), RHS.get() }; - OverloadCandidateSet CandidateSet(QuestionLoc); + OverloadCandidateSet CandidateSet(QuestionLoc, + OverloadCandidateSet::CSK_Operator); Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, CandidateSet); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 382901667e..9c90ac0d9a 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -4411,7 +4411,7 @@ InitializationSequence::InitializationSequence(Sema &S, const InitializationKind &Kind, MultiExprArg Args, bool TopLevelOfInitList) - : FailedCandidateSet(Kind.getLocation()) { + : FailedCandidateSet(Kind.getLocation(), OverloadCandidateSet::CSK_Normal) { InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); } @@ -4945,7 +4945,7 @@ static ExprResult CopyObject(Sema &S, // Only consider constructors and constructor templates. Per // C++0x [dcl.init]p16, second bullet to class types, this initialization // is direct-initialization. - OverloadCandidateSet CandidateSet(Loc); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); LookupCopyAndMoveConstructors(S, CandidateSet, Class, CurInitExpr); bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -5053,7 +5053,7 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, return; // Find constructors which would have been considered. - OverloadCandidateSet CandidateSet(Loc); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); LookupCopyAndMoveConstructors( S, CandidateSet, cast(Record->getDecl()), CurInitExpr); 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(); - 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(Found)) { - if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) - Functions.addDecl(Op, Op.getAccess()); // FIXME: canonical FD - } else if (FunctionTemplateDecl *FunTmpl - = dyn_cast(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 Args, - ADLResult &Result) { +void Sema::ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, + ArrayRef 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(D)) D = cast(D)->getTargetDecl(); - if (isa(D)) { - if (Operator && - !IsAcceptableNonMemberOperatorCandidate(cast(D), - T1, T2, Context)) - continue; - } else if (!isa(D)) + if (!isa(D) && !isa(D)) continue; Result.insert(D); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 90710205db..1f2875cd6f 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1127,7 +1127,8 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } // Attempt user-defined conversion. - OverloadCandidateSet Conversions(From->getExprLoc()); + OverloadCandidateSet Conversions(From->getExprLoc(), + OverloadCandidateSet::CSK_Normal); OverloadingResult UserDefResult = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, AllowExplicit, AllowObjCConversionOnExplicit); @@ -3244,7 +3245,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, bool Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { ImplicitConversionSequence ICS; - OverloadCandidateSet CandidateSet(From->getExprLoc()); + OverloadCandidateSet CandidateSet(From->getExprLoc(), + OverloadCandidateSet::CSK_Normal); OverloadingResult OvResult = IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, CandidateSet, false, false); @@ -4071,7 +4073,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, CXXRecordDecl *T2RecordDecl = dyn_cast(T2->getAs()->getDecl()); - OverloadCandidateSet CandidateSet(DeclLoc); + OverloadCandidateSet CandidateSet(DeclLoc, OverloadCandidateSet::CSK_Normal); std::pair Conversions = T2RecordDecl->getVisibleConversionFunctions(); @@ -5419,7 +5421,7 @@ ExprResult Sema::PerformContextualImplicitConversion( // If one unique T is found: // First, build a candidate set from the previously recorded // potentially viable conversions. - OverloadCandidateSet CandidateSet(Loc); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); collectViableConversionCandidates(*this, From, ToType, ViableConversions, CandidateSet); @@ -5476,6 +5478,45 @@ ExprResult Sema::PerformContextualImplicitConversion( return finishContextualImplicitConversion(*this, Loc, From, Converter); } +/// 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(ASTContext &Context, + FunctionDecl *Fn, + ArrayRef Args) { + QualType T1 = Args[0]->getType(); + QualType T2 = Args.size() > 1 ? Args[1]->getType() : QualType(); + + if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType())) + return true; + + if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) + return true; + + const FunctionProtoType *Proto = Fn->getType()->getAs(); + 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; +} + /// AddOverloadCandidate - Adds the given function to the set of /// candidate functions, using the given function call arguments. If /// @p SuppressUserConversions, then don't allow user-defined @@ -5519,6 +5560,17 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, if (!CandidateSet.isNewCandidate(Function)) return; + // C++ [over.match.oper]p3: + // 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. + if (CandidateSet.getKind() == OverloadCandidateSet::CSK_Operator && + !IsAcceptableNonMemberOperatorCandidate(Context, Function, Args)) + return; + // C++11 [class.copy]p11: [DR1402] // A defaulted move constructor that is defined as deleted is ignored by // overload resolution. @@ -8084,7 +8136,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, /// candidate set (C++ [basic.lookup.argdep]). void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, - bool Operator, SourceLocation Loc, + SourceLocation Loc, ArrayRef Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, @@ -8099,7 +8151,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Operator, Loc, Args, Fns); + ArgumentDependentLookup(Name, Loc, Args, Fns); // Erase all of the candidates we already knew about. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), @@ -10197,8 +10249,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, /*KnownValid*/ true); if (ULE->requiresADL()) - AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false, - ULE->getExprLoc(), + AddArgumentDependentLookupCandidates(ULE->getName(), ULE->getExprLoc(), Args, ExplicitTemplateArgs, CandidateSet, PartialOverloading); } @@ -10225,6 +10276,7 @@ static bool canBeDeclaredInNamespace(const DeclarationName &Name) { static bool DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS, LookupResult &R, + OverloadCandidateSet::CandidateSetKind CSK, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args) { if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) @@ -10246,7 +10298,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, return false; } - OverloadCandidateSet Candidates(FnLoc); + OverloadCandidateSet Candidates(FnLoc, CSK); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) AddOverloadedCallCandidate(SemaRef, I.getPair(), ExplicitTemplateArgs, Args, @@ -10330,6 +10382,7 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName); return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R, + OverloadCandidateSet::CSK_Operator, /*ExplicitTemplateArgs=*/0, Args); } @@ -10390,6 +10443,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, (CorrectionCandidateCallback*)&Validator : (CorrectionCandidateCallback*)&RejectAll; if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, + OverloadCandidateSet::CSK_Normal, ExplicitTemplateArgs, Args) && (!EmptyLookup || SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC, @@ -10568,7 +10622,8 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, SourceLocation RParenLoc, Expr *ExecConfig, bool AllowTypoCorrection) { - OverloadCandidateSet CandidateSet(Fn->getExprLoc()); + OverloadCandidateSet CandidateSet(Fn->getExprLoc(), + OverloadCandidateSet::CSK_Normal); ExprResult result; if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet, @@ -10657,7 +10712,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, } // Build an empty overload set. - OverloadCandidateSet CandidateSet(OpLoc); + OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false); @@ -10666,9 +10721,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); // Add candidates from ADL. - AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, OpLoc, - ArgsArray, /*ExplicitTemplateArgs*/ 0, - CandidateSet); + AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray, + /*ExplicitTemplateArgs*/0, CandidateSet); // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -10872,7 +10926,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); // Build an empty overload set. - OverloadCandidateSet CandidateSet(OpLoc); + OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. AddFunctionCandidates(Fns, Args, CandidateSet, false); @@ -10881,8 +10935,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet); // Add candidates from ADL. - AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, - OpLoc, Args, + AddArgumentDependentLookupCandidates(OpName, OpLoc, Args, /*ExplicitTemplateArgs*/ 0, CandidateSet); @@ -11108,7 +11161,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, return ExprError(); // Build an empty overload set. - OverloadCandidateSet CandidateSet(LLoc); + OverloadCandidateSet CandidateSet(LLoc, OverloadCandidateSet::CSK_Operator); // Subscript can only be overloaded as a member function. @@ -11331,7 +11384,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, : UnresExpr->getBase()->Classify(Context); // Add overload candidates - OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc()); + OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc(), + OverloadCandidateSet::CSK_Normal); // FIXME: avoid copy. TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; @@ -11515,7 +11569,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // operators of T. The function call operators of T are obtained by // ordinary lookup of the name operator() in the context of // (E).operator(). - OverloadCandidateSet CandidateSet(LParenLoc); + OverloadCandidateSet CandidateSet(LParenLoc, + OverloadCandidateSet::CSK_Operator); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); if (RequireCompleteType(LParenLoc, Object.get()->getType(), @@ -11794,7 +11849,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, // overload resolution mechanism (13.3). DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow); - OverloadCandidateSet CandidateSet(Loc); + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Operator); const RecordType *BaseRecord = Base->getType()->getAs(); if (RequireCompleteType(Loc, Base->getType(), @@ -11896,7 +11951,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, TemplateArgumentListInfo *TemplateArgs) { SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc(); - OverloadCandidateSet CandidateSet(UDSuffixLoc); + OverloadCandidateSet CandidateSet(UDSuffixLoc, + OverloadCandidateSet::CSK_Normal); AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, TemplateArgs); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 2be5d5cb83..f40b409c92 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -2194,7 +2194,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, return StmtError(); } } else { - OverloadCandidateSet CandidateSet(RangeLoc); + OverloadCandidateSet CandidateSet(RangeLoc, + OverloadCandidateSet::CSK_Normal); Sema::BeginEndFunction BEFFailure; ForRangeStatus RangeStatus = BuildNonArrayForRange(*this, S, BeginRangeRef.get(), diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 4094f5a716..22913104d7 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -9759,11 +9759,7 @@ TreeTransform::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, if (UnresolvedLookupExpr *ULE = dyn_cast(Callee)) { assert(ULE->requiresADL()); - - for (auto I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) - SemaRef.addOverloadedOperatorToUnresolvedSet( - Functions, I.getPair(), First->getType(), - Second ? Second->getType() : QualType()); + Functions.append(ULE->decls_begin(), ULE->decls_end()); } else { // If we've resolved this to a particular non-member function, just call // that function. If we resolved it to a member function, diff --git a/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp b/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp index b3cc3bf41c..d88d5beb4e 100644 --- a/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp +++ b/test/CXX/over/over.match/over.match.funcs/over.match.oper/p3.cpp @@ -7,19 +7,17 @@ namespace bullet2 { // candidates. struct B { template B(T); }; -int operator~(B); // expected-note {{declared prior to the call site}} +int operator~(B); template int operator%(B, T); enum class E { e }; -// FIXME: This is the wrong diagnostic. -template int f(T t) { return ~t; } // expected-error {{call to}} -template int f(T t, U u) { return t % u; } +template int f(T t) { return ~t; } // expected-error {{invalid argument type}} +template int f(T t, U u) { return t % u; } // expected-error {{invalid operands to}} int b1 = ~E::e; // expected-error {{invalid argument type}} int b2 = f(E::e); // expected-note {{in instantiation of}} int b3 = f(0, E::e); -// FIXME: This should be rejected. -int b4 = f(E::e, 0); +int b4 = f(E::e, 0); // expected-note {{in instantiation of}} }