summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp142
1 files changed, 80 insertions, 62 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6f8ad637d9b..27e1101b482 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -11035,6 +11035,7 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
unsigned ConvIdx = 0;
unsigned ArgIdx = 0;
ArrayRef<QualType> ParamTypes;
+ bool Reversed = Cand->RewriteKind & CRK_Reversed;
if (Cand->IsSurrogate) {
QualType ConvType
@@ -11048,7 +11049,7 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
ParamTypes =
Cand->Function->getType()->castAs<FunctionProtoType>()->getParamTypes();
if (isa<CXXMethodDecl>(Cand->Function) &&
- !isa<CXXConstructorDecl>(Cand->Function)) {
+ !isa<CXXConstructorDecl>(Cand->Function) && !Reversed) {
// Conversion 0 is 'this', which doesn't have a corresponding parameter.
ConvIdx = 1;
if (CSK == OverloadCandidateSet::CSK_Operator &&
@@ -11063,7 +11064,6 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
}
// Fill in the rest of the conversions.
- bool Reversed = Cand->RewriteKind & CRK_Reversed;
for (unsigned ParamIdx = Reversed ? ParamTypes.size() - 1 : 0;
ConvIdx != ConvCount;
++ConvIdx, ++ArgIdx, ParamIdx += (Reversed ? -1 : 1)) {
@@ -12755,6 +12755,70 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
+/// Perform lookup for an overloaded binary operator.
+void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
+ OverloadedOperatorKind Op,
+ const UnresolvedSetImpl &Fns,
+ ArrayRef<Expr *> Args, bool PerformADL) {
+ SourceLocation OpLoc = CandidateSet.getLocation();
+
+ OverloadedOperatorKind ExtraOp =
+ CandidateSet.getRewriteInfo().AllowRewrittenCandidates
+ ? getRewrittenOverloadedOperator(Op)
+ : OO_None;
+
+ // Add the candidates from the given function set. This also adds the
+ // rewritten candidates using these functions if necessary.
+ AddNonMemberOperatorCandidates(Fns, Args, CandidateSet);
+
+ // Add operator candidates that are member functions.
+ AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(Op))
+ AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet,
+ OverloadCandidateParamOrder::Reversed);
+
+ // In C++20, also add any rewritten member candidates.
+ if (ExtraOp) {
+ AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(ExtraOp))
+ AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
+ CandidateSet,
+ OverloadCandidateParamOrder::Reversed);
+ }
+
+ // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
+ // performed for an assignment operator (nor for operator[] nor operator->,
+ // which don't get here).
+ if (Op != OO_Equal && PerformADL) {
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
+ AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
+ CandidateSet);
+ if (ExtraOp) {
+ DeclarationName ExtraOpName =
+ Context.DeclarationNames.getCXXOperatorName(ExtraOp);
+ AddArgumentDependentLookupCandidates(ExtraOpName, OpLoc, Args,
+ /*ExplicitTemplateArgs*/ nullptr,
+ CandidateSet);
+ }
+ }
+
+ // Add builtin operator candidates.
+ //
+ // FIXME: We don't add any rewritten candidates here. This is strictly
+ // incorrect; a builtin candidate could be hidden by a non-viable candidate,
+ // resulting in our selecting a rewritten builtin candidate. For example:
+ //
+ // enum class E { e };
+ // bool operator!=(E, E) requires false;
+ // bool k = E::e != E::e;
+ //
+ // ... should select the rewritten builtin candidate 'operator==(E, E)'. But
+ // it seems unreasonable to consider rewritten builtin candidates. A core
+ // issue has been filed proposing to removed this requirement.
+ AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
+}
+
/// Create a binary operation that may resolve to an overloaded
/// operator.
///
@@ -12783,7 +12847,6 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
AllowRewrittenCandidates = false;
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
- DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
// If either side is type-dependent, create an appropriate dependent
// expression.
@@ -12805,6 +12868,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// FIXME: save results of ADL from here?
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
// TODO: provide better source location info in DNLoc component.
+ DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
Context, NamingClass, NestedNameSpecifierLoc(), OpNameInfo,
@@ -12838,63 +12902,11 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (Opc == BO_PtrMemD)
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
- // Build an empty overload set.
+ // Build the overload set.
OverloadCandidateSet CandidateSet(
OpLoc, OverloadCandidateSet::CSK_Operator,
OverloadCandidateSet::OperatorRewriteInfo(Op, AllowRewrittenCandidates));
-
- OverloadedOperatorKind ExtraOp =
- AllowRewrittenCandidates ? getRewrittenOverloadedOperator(Op) : OO_None;
-
- // Add the candidates from the given function set. This also adds the
- // rewritten candidates using these functions if necessary.
- AddNonMemberOperatorCandidates(Fns, Args, CandidateSet);
-
- // Add operator candidates that are member functions.
- AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(Op))
- AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet,
- OverloadCandidateParamOrder::Reversed);
-
- // In C++20, also add any rewritten member candidates.
- if (ExtraOp) {
- AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(ExtraOp))
- AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
- CandidateSet,
- OverloadCandidateParamOrder::Reversed);
- }
-
- // Add candidates from ADL. Per [over.match.oper]p2, this lookup is not
- // performed for an assignment operator (nor for operator[] nor operator->,
- // which don't get here).
- if (Opc != BO_Assign && PerformADL) {
- AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
- /*ExplicitTemplateArgs*/ nullptr,
- CandidateSet);
- if (ExtraOp) {
- DeclarationName ExtraOpName =
- Context.DeclarationNames.getCXXOperatorName(ExtraOp);
- AddArgumentDependentLookupCandidates(ExtraOpName, OpLoc, Args,
- /*ExplicitTemplateArgs*/ nullptr,
- CandidateSet);
- }
- }
-
- // Add builtin operator candidates.
- //
- // FIXME: We don't add any rewritten candidates here. This is strictly
- // incorrect; a builtin candidate could be hidden by a non-viable candidate,
- // resulting in our selecting a rewritten builtin candidate. For example:
- //
- // enum class E { e };
- // bool operator!=(E, E) requires false;
- // bool k = E::e != E::e;
- //
- // ... should select the rewritten builtin candidate 'operator==(E, E)'. But
- // it seems unreasonable to consider rewritten builtin candidates. A core
- // issue has been filed proposing to removed this requirement.
- AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
+ LookupOverloadedBinOp(CandidateSet, Op, Fns, Args, PerformADL);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -13150,14 +13162,20 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
case OR_Deleted:
if (isImplicitlyDeleted(Best->Function)) {
- CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
- Diag(OpLoc, diag::err_ovl_deleted_special_oper)
- << Context.getRecordType(Method->getParent())
- << getSpecialMember(Method);
+ FunctionDecl *DeletedFD = Best->Function;
+ DefaultedFunctionKind DFK = getDefaultedFunctionKind(DeletedFD);
+ if (DFK.isSpecialMember()) {
+ Diag(OpLoc, diag::err_ovl_deleted_special_oper)
+ << Args[0]->getType() << DFK.asSpecialMember();
+ } else {
+ assert(DFK.isComparison());
+ Diag(OpLoc, diag::err_ovl_deleted_comparison)
+ << Args[0]->getType() << DeletedFD;
+ }
// The user probably meant to call this special member. Just
// explain why it's deleted.
- NoteDeletedFunction(Method);
+ NoteDeletedFunction(DeletedFD);
return ExprError();
}
CandidateSet.NoteCandidates(
OpenPOWER on IntegriCloud