aboutsummaryrefslogtreecommitdiff
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.cpp606
1 files changed, 398 insertions, 208 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d72cc33ed0f5..d68337a26d97 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -12,14 +12,17 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DependenceFlags.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
@@ -30,12 +33,13 @@
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Casting.h"
#include <algorithm>
#include <cstdlib>
+#include <optional>
using namespace clang;
using namespace sema;
@@ -63,9 +67,8 @@ static ExprResult CreateFunctionRefExpr(
// being used.
if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc))
return ExprError();
- DeclRefExpr *DRE =
- DeclRefExpr::Create(S.Context, Fn->getQualifierLoc(), SourceLocation(),
- Fn, false, Loc, Fn->getType(), VK_LValue, FoundDecl);
+ DeclRefExpr *DRE = new (S.Context)
+ DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
@@ -355,7 +358,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
- if (Optional<llvm::APSInt> IntConstantValue =
+ if (std::optional<llvm::APSInt> IntConstantValue =
Initializer->getIntegerConstantExpr(Ctx)) {
// Convert the integer to the floating type.
llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
@@ -438,7 +441,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
- Optional<llvm::APSInt> OptInitializerValue;
+ std::optional<llvm::APSInt> OptInitializerValue;
if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) {
// Such conversions on variables are always narrowing.
return NK_Variable_Narrowing;
@@ -637,7 +640,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
auto *Saved = new (Context) DFIDeducedMismatchArgs;
Saved->FirstArg = Info.FirstArg;
Saved->SecondArg = Info.SecondArg;
- Saved->TemplateArgs = Info.take();
+ Saved->TemplateArgs = Info.takeSugared();
Saved->CallArgIndex = Info.CallArgIndex;
Result.Data = Saved;
break;
@@ -666,7 +669,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
}
case Sema::TDK_SubstitutionFailure:
- Result.Data = Info.take();
+ Result.Data = Info.takeSugared();
if (Info.hasSFINAEDiagnostic()) {
PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt(
SourceLocation(), PartialDiagnostic::NullDiagnostic());
@@ -677,7 +680,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_ConstraintsNotSatisfied: {
CNSInfo *Saved = new (Context) CNSInfo;
- Saved->TemplateArgs = Info.take();
+ Saved->TemplateArgs = Info.takeSugared();
Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction;
Result.Data = Saved;
break;
@@ -685,6 +688,7 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_Success:
case Sema::TDK_NonDependentConversionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
llvm_unreachable("not a deduction failure");
}
@@ -734,6 +738,7 @@ void DeductionFailureInfo::Destroy() {
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
break;
}
}
@@ -771,6 +776,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
break;
}
@@ -806,6 +812,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
break;
}
@@ -837,6 +844,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
break;
}
@@ -868,24 +876,95 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
// Unhandled
case Sema::TDK_MiscellaneousDeductionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
break;
}
return nullptr;
}
-llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
+std::optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested:
return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex;
default:
- return llvm::None;
+ return std::nullopt;
}
}
-bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed(
+static bool FunctionsCorrespond(ASTContext &Ctx, const FunctionDecl *X,
+ const FunctionDecl *Y) {
+ if (!X || !Y)
+ return false;
+ if (X->getNumParams() != Y->getNumParams())
+ return false;
+ for (unsigned I = 0; I < X->getNumParams(); ++I)
+ if (!Ctx.hasSameUnqualifiedType(X->getParamDecl(I)->getType(),
+ Y->getParamDecl(I)->getType()))
+ return false;
+ if (auto *FTX = X->getDescribedFunctionTemplate()) {
+ auto *FTY = Y->getDescribedFunctionTemplate();
+ if (!FTY)
+ return false;
+ if (!Ctx.isSameTemplateParameterList(FTX->getTemplateParameters(),
+ FTY->getTemplateParameters()))
+ return false;
+ }
+ return true;
+}
+
+static bool shouldAddReversedEqEq(Sema &S, SourceLocation OpLoc,
+ Expr *FirstOperand, FunctionDecl *EqFD) {
+ assert(EqFD->getOverloadedOperator() ==
+ OverloadedOperatorKind::OO_EqualEqual);
+ // C++2a [over.match.oper]p4:
+ // A non-template function or function template F named operator== is a
+ // rewrite target with first operand o unless a search for the name operator!=
+ // in the scope S from the instantiation context of the operator expression
+ // finds a function or function template that would correspond
+ // ([basic.scope.scope]) to F if its name were operator==, where S is the
+ // scope of the class type of o if F is a class member, and the namespace
+ // scope of which F is a member otherwise. A function template specialization
+ // named operator== is a rewrite target if its function template is a rewrite
+ // target.
+ DeclarationName NotEqOp = S.Context.DeclarationNames.getCXXOperatorName(
+ OverloadedOperatorKind::OO_ExclaimEqual);
+ if (isa<CXXMethodDecl>(EqFD)) {
+ // If F is a class member, search scope is class type of first operand.
+ QualType RHS = FirstOperand->getType();
+ auto *RHSRec = RHS->getAs<RecordType>();
+ if (!RHSRec)
+ return true;
+ LookupResult Members(S, NotEqOp, OpLoc,
+ Sema::LookupNameKind::LookupMemberName);
+ S.LookupQualifiedName(Members, RHSRec->getDecl());
+ Members.suppressDiagnostics();
+ for (NamedDecl *Op : Members)
+ if (FunctionsCorrespond(S.Context, EqFD, Op->getAsFunction()))
+ return false;
+ return true;
+ }
+ // Otherwise the search scope is the namespace scope of which F is a member.
+ LookupResult NonMembers(S, NotEqOp, OpLoc,
+ Sema::LookupNameKind::LookupOperatorName);
+ S.LookupName(NonMembers,
+ S.getScopeForContext(EqFD->getEnclosingNamespaceContext()));
+ NonMembers.suppressDiagnostics();
+ for (NamedDecl *Op : NonMembers) {
+ auto *FD = Op->getAsFunction();
+ if(auto* UD = dyn_cast<UsingShadowDecl>(Op))
+ FD = UD->getUnderlyingDecl()->getAsFunction();
+ if (FunctionsCorrespond(S.Context, EqFD, FD) &&
+ declaresSameEntity(cast<Decl>(EqFD->getDeclContext()),
+ cast<Decl>(Op->getDeclContext())))
+ return false;
+ }
+ return true;
+}
+
+bool OverloadCandidateSet::OperatorRewriteInfo::allowsReversed(
OverloadedOperatorKind Op) {
if (!AllowRewrittenCandidates)
return false;
@@ -893,14 +972,21 @@ bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed(
}
bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed(
- ASTContext &Ctx, const FunctionDecl *FD) {
- if (!shouldAddReversed(FD->getDeclName().getCXXOverloadedOperator()))
+ Sema &S, ArrayRef<Expr *> OriginalArgs, FunctionDecl *FD) {
+ auto Op = FD->getOverloadedOperator();
+ if (!allowsReversed(Op))
return false;
+ if (Op == OverloadedOperatorKind::OO_EqualEqual) {
+ assert(OriginalArgs.size() == 2);
+ if (!shouldAddReversedEqEq(
+ S, OpLoc, /*FirstOperand in reversed args*/ OriginalArgs[1], FD))
+ return false;
+ }
// Don't bother adding a reversed candidate that can never be a better
// match than the non-reversed version.
return FD->getNumParams() != 2 ||
- !Ctx.hasSameUnqualifiedType(FD->getParamDecl(0)->getType(),
- FD->getParamDecl(1)->getType()) ||
+ !S.Context.hasSameUnqualifiedType(FD->getParamDecl(0)->getType(),
+ FD->getParamDecl(1)->getType()) ||
FD->hasAttr<EnableIfAttr>();
}
@@ -1069,6 +1155,15 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
!shouldLinkPossiblyHiddenDecl(*I, New))
continue;
+ // C++20 [temp.friend] p9: A non-template friend declaration with a
+ // requires-clause shall be a definition. A friend function template
+ // with a constraint that depends on a template parameter from an
+ // enclosing template shall be a definition. Such a constrained friend
+ // function or function template declaration does not declare the same
+ // function or function template as a declaration in any other scope.
+ if (Context.FriendsDifferByConstraints(OldF, New))
+ continue;
+
Match = *I;
return Ovl_Match;
}
@@ -1185,25 +1280,52 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
!FunctionParamTypesAreEqual(OldType, NewType)))
return true;
- // C++ [temp.over.link]p4:
- // The signature of a function template consists of its function
- // signature, its return type and its template parameter list. The names
- // of the template parameters are significant only for establishing the
- // relationship between the template parameters and the rest of the
- // signature.
- //
- // We check the return type and template parameter lists for function
- // templates first; the remaining checks follow.
- //
- // However, we don't consider either of these when deciding whether
- // a member introduced by a shadow declaration is hidden.
- if (!UseMemberUsingDeclRules && NewTemplate &&
- (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
- OldTemplate->getTemplateParameters(),
- false, TPL_TemplateMatch) ||
- !Context.hasSameType(Old->getDeclaredReturnType(),
- New->getDeclaredReturnType())))
- return true;
+ if (NewTemplate) {
+ // C++ [temp.over.link]p4:
+ // The signature of a function template consists of its function
+ // signature, its return type and its template parameter list. The names
+ // of the template parameters are significant only for establishing the
+ // relationship between the template parameters and the rest of the
+ // signature.
+ //
+ // We check the return type and template parameter lists for function
+ // templates first; the remaining checks follow.
+ bool SameTemplateParameterList = TemplateParameterListsAreEqual(
+ NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch);
+ bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(),
+ New->getDeclaredReturnType());
+ // FIXME(GH58571): Match template parameter list even for non-constrained
+ // template heads. This currently ensures that the code prior to C++20 is
+ // not newly broken.
+ bool ConstraintsInTemplateHead =
+ NewTemplate->getTemplateParameters()->hasAssociatedConstraints() ||
+ OldTemplate->getTemplateParameters()->hasAssociatedConstraints();
+ // C++ [namespace.udecl]p11:
+ // The set of declarations named by a using-declarator that inhabits a
+ // class C does not include member functions and member function
+ // templates of a base class that "correspond" to (and thus would
+ // conflict with) a declaration of a function or function template in
+ // C.
+ // Comparing return types is not required for the "correspond" check to
+ // decide whether a member introduced by a shadow declaration is hidden.
+ if (UseMemberUsingDeclRules && ConstraintsInTemplateHead &&
+ !SameTemplateParameterList)
+ return true;
+ if (!UseMemberUsingDeclRules &&
+ (!SameTemplateParameterList || !SameReturnType))
+ return true;
+ }
+
+ if (ConsiderRequiresClauses) {
+ Expr *NewRC = New->getTrailingRequiresClause(),
+ *OldRC = Old->getTrailingRequiresClause();
+ if ((NewRC != nullptr) != (OldRC != nullptr))
+ return true;
+
+ if (NewRC && !AreConstraintExpressionsEqual(Old, OldRC, New, NewRC))
+ return true;
+ }
// If the function is a class member, its signature includes the
// cv-qualifiers (if any) and ref-qualifier (if any) on the function itself.
@@ -1221,14 +1343,15 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
if (!UseMemberUsingDeclRules &&
(OldMethod->getRefQualifier() == RQ_None ||
NewMethod->getRefQualifier() == RQ_None)) {
- // C++0x [over.load]p2:
- // - Member function declarations with the same name and the same
- // parameter-type-list as well as member function template
- // declarations with the same name, the same parameter-type-list, and
- // the same template parameter lists cannot be overloaded if any of
- // them, but not all, have a ref-qualifier (8.3.5).
+ // C++20 [over.load]p2:
+ // - Member function declarations with the same name, the same
+ // parameter-type-list, and the same trailing requires-clause (if
+ // any), as well as member function template declarations with the
+ // same name, the same parameter-type-list, the same trailing
+ // requires-clause (if any), and the same template-head, cannot be
+ // overloaded if any of them, but not all, have a ref-qualifier.
Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
- << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
+ << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
Diag(OldMethod->getLocation(), diag::note_previous_declaration);
}
return true;
@@ -1292,23 +1415,6 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
}
}
- if (ConsiderRequiresClauses) {
- Expr *NewRC = New->getTrailingRequiresClause(),
- *OldRC = Old->getTrailingRequiresClause();
- if ((NewRC != nullptr) != (OldRC != nullptr))
- // RC are most certainly different - these are overloads.
- return true;
-
- if (NewRC) {
- llvm::FoldingSetNodeID NewID, OldID;
- NewRC->Profile(NewID, Context, /*Canonical=*/true);
- OldRC->Profile(OldID, Context, /*Canonical=*/true);
- if (NewID != OldID)
- // RCs are not equivalent - these are overloads.
- return true;
- }
- }
-
// The signatures match; this is not an overload.
return false;
}
@@ -1620,7 +1726,7 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
/// conversion.
static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
ImplicitConversionKind &ICK, Expr *From,
- bool InOverloadResolution) {
+ bool InOverloadResolution, bool CStyle) {
// We need at least one of these types to be a vector type to have a vector
// conversion.
if (!ToType->isVectorType() && !FromType->isVectorType())
@@ -1665,7 +1771,7 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
if (S.isLaxVectorConversion(FromType, ToType) &&
S.anyAltivecTypes(FromType, ToType) &&
!S.areSameVectorElemTypes(FromType, ToType) &&
- !InOverloadResolution) {
+ !InOverloadResolution && !CStyle) {
S.Diag(From->getBeginLoc(), diag::warn_deprecated_lax_vec_conv_all)
<< FromType << ToType;
}
@@ -1918,7 +2024,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
} else if (IsVectorConversion(S, FromType, ToType, SecondICK, From,
- InOverloadResolution)) {
+ InOverloadResolution, CStyle)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
} else if (!S.getLangOpts().CPlusPlus &&
@@ -2073,9 +2179,9 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// int can represent all the values of the source type; otherwise,
// the source rvalue can be converted to an rvalue of type unsigned
// int (C++ 4.5p1).
- if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() &&
+ if (Context.isPromotableIntegerType(FromType) && !FromType->isBooleanType() &&
!FromType->isEnumeralType()) {
- if (// We can promote any signed, promotable integer type to an int
+ if ( // We can promote any signed, promotable integer type to an int
(FromType->isSignedIntegerType() ||
// We can promote any unsigned integer type whose size is
// less than int to an int.
@@ -2187,7 +2293,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
// compatibility.
if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
- Optional<llvm::APSInt> BitWidth;
+ std::optional<llvm::APSInt> BitWidth;
if (FromType->isIntegralType(Context) &&
(BitWidth =
MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) {
@@ -3506,7 +3612,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(
Info.ConstructorTmpl, Info.FoundDecl,
- /*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs),
+ /*ExplicitArgs*/ nullptr, llvm::ArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions,
/*PartialOverloading*/ false,
AllowExplicit == AllowedExplicit::All);
@@ -3514,8 +3620,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
- llvm::makeArrayRef(Args, NumArgs),
- CandidateSet, SuppressUserConversions,
+ llvm::ArrayRef(Args, NumArgs), CandidateSet,
+ SuppressUserConversions,
/*PartialOverloading*/ false,
AllowExplicit == AllowedExplicit::All);
}
@@ -4495,15 +4601,6 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
return ImplicitConversionSequence::Indistinguishable;
}
-/// Determine whether the given type is valid, e.g., it is not an invalid
-/// C++ class.
-static bool isTypeValid(QualType T) {
- if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
- return !Record->isInvalidDecl();
-
- return true;
-}
-
static QualType withoutUnaligned(ASTContext &Ctx, QualType T) {
if (!T.getQualifiers().hasUnaligned())
return T;
@@ -4553,7 +4650,6 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
if (UnqualT1 == UnqualT2) {
// Nothing to do.
} else if (isCompleteType(Loc, OrigT2) &&
- isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
IsDerivedFrom(Loc, UnqualT2, UnqualT1))
Conv |= ReferenceConversions::DerivedToBase;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
@@ -5096,7 +5192,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
}
if (CT->getSize().ugt(e)) {
// Need an init from empty {}, is there one?
- InitListExpr EmptyList(S.Context, From->getEndLoc(), None,
+ InitListExpr EmptyList(S.Context, From->getEndLoc(), std::nullopt,
From->getEndLoc());
EmptyList.setType(S.Context.VoidTy);
DfltElt = TryListConversion(
@@ -5725,7 +5821,8 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
- llvm_unreachable("ellipsis conversion in converted constant expression");
+ case ImplicitConversionSequence::StaticObjectArgumentConversion:
+ llvm_unreachable("bad conversion in converted constant expression");
}
// Check that we would only use permitted conversions.
@@ -5760,9 +5857,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
// C++2a [intro.execution]p5:
// A full-expression is [...] a constant-expression [...]
- Result =
- S.ActOnFinishFullExpr(Result.get(), From->getExprLoc(),
- /*DiscardedValue=*/false, /*IsConstexpr=*/true);
+ Result = S.ActOnFinishFullExpr(Result.get(), From->getExprLoc(),
+ /*DiscardedValue=*/false, /*IsConstexpr=*/true,
+ CCE == Sema::CCEKind::CCEK_TemplateArg);
if (Result.isInvalid())
return Result;
@@ -5909,6 +6006,7 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
case ImplicitConversionSequence::BadConversion:
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::EllipsisConversion:
+ case ImplicitConversionSequence::StaticObjectArgumentConversion:
break;
case ImplicitConversionSequence::UserDefinedConversion:
@@ -6242,7 +6340,7 @@ ExprResult Sema::PerformContextualImplicitConversion(
HadMultipleCandidates,
ExplicitConversions))
return ExprError();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OR_Deleted:
// We'll complain below about a non-integral condition type.
break;
@@ -6422,8 +6520,11 @@ void Sema::AddOverloadCandidate(
}
}
- if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
- !Function->getAttr<TargetAttr>()->isDefaultVersion()) {
+ if (Function->isMultiVersion() &&
+ ((Function->hasAttr<TargetAttr>() &&
+ !Function->getAttr<TargetAttr>()->isDefaultVersion()) ||
+ (Function->hasAttr<TargetVersionAttr>() &&
+ !Function->getAttr<TargetVersionAttr>()->isDefaultVersion()))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_non_default_multiversion_function;
return;
@@ -6516,7 +6617,8 @@ void Sema::AddOverloadCandidate(
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Function, Satisfaction) ||
+ if (CheckFunctionConstraints(Function, Satisfaction, /*Loc*/ {},
+ /*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -6742,7 +6844,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function,
// very difficult. Ideally, we should handle them more gracefully.
if (EIA->getCond()->isValueDependent() ||
!EIA->getCond()->EvaluateWithSubstitution(
- Result, Context, Function, llvm::makeArrayRef(ConvertedArgs)))
+ Result, Context, Function, llvm::ArrayRef(ConvertedArgs)))
return EIA;
if (!Result.isInt() || !Result.getInt().getBoolValue())
@@ -6914,7 +7016,7 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType,
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
ObjectType, ObjectClassification, Args, CandidateSet,
- SuppressUserConversions, false, None, PO);
+ SuppressUserConversions, false, std::nullopt, PO);
}
}
@@ -6994,17 +7096,27 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
Candidate.Viable = true;
- if (Method->isStatic() || ObjectType.isNull())
- // The implicit object argument is ignored.
+ unsigned FirstConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0;
+ if (ObjectType.isNull())
Candidate.IgnoreObjectArgument = true;
- else {
- unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0;
+ else if (Method->isStatic()) {
+ // [over.best.ics.general]p8
+ // When the parameter is the implicit object parameter of a static member
+ // function, the implicit conversion sequence is a standard conversion
+ // sequence that is neither better nor worse than any other standard
+ // conversion sequence.
+ //
+ // This is a rule that was introduced in C++23 to support static lambdas. We
+ // apply it retroactively because we want to support static lambdas as an
+ // extension and it doesn't hurt previous code.
+ Candidate.Conversions[FirstConvIdx].setStaticObjectArgument();
+ } else {
// Determine the implicit conversion sequence for the object
// parameter.
- Candidate.Conversions[ConvIdx] = TryObjectArgumentInitialization(
+ Candidate.Conversions[FirstConvIdx] = TryObjectArgumentInitialization(
*this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
Method, ActingContext);
- if (Candidate.Conversions[ConvIdx].isBad()) {
+ if (Candidate.Conversions[FirstConvIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
@@ -7022,7 +7134,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckFunctionConstraints(Method, Satisfaction) ||
+ if (CheckFunctionConstraints(Method, Satisfaction, /*Loc*/ {},
+ /*ForOverloadResolution*/ true) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -7071,8 +7184,11 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
return;
}
- if (Method->isMultiVersion() && Method->hasAttr<TargetAttr>() &&
- !Method->getAttr<TargetAttr>()->isDefaultVersion()) {
+ if (Method->isMultiVersion() &&
+ ((Method->hasAttr<TargetAttr>() &&
+ !Method->getAttr<TargetAttr>()->isDefaultVersion()) ||
+ (Method->hasAttr<TargetVersionAttr>() &&
+ !Method->getAttr<TargetVersionAttr>()->isDefaultVersion()))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_non_default_multiversion_function;
}
@@ -7518,15 +7634,18 @@ void Sema::AddConversionCandidate(
}
if (EnableIfAttr *FailedAttr =
- CheckEnableIf(Conversion, CandidateSet.getLocation(), None)) {
+ CheckEnableIf(Conversion, CandidateSet.getLocation(), std::nullopt)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
- if (Conversion->isMultiVersion() && Conversion->hasAttr<TargetAttr>() &&
- !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) {
+ if (Conversion->isMultiVersion() &&
+ ((Conversion->hasAttr<TargetAttr>() &&
+ !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) ||
+ (Conversion->hasAttr<TargetVersionAttr>() &&
+ !Conversion->getAttr<TargetVersionAttr>()->isDefaultVersion()))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_non_default_multiversion_function;
}
@@ -7689,7 +7808,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
if (EnableIfAttr *FailedAttr =
- CheckEnableIf(Conversion, CandidateSet.getLocation(), None)) {
+ CheckEnableIf(Conversion, CandidateSet.getLocation(), std::nullopt)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -7721,7 +7840,7 @@ void Sema::AddNonMemberOperatorCandidates(
if (FunTmpl) {
AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs,
FunctionArgs, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD))
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD))
AddTemplateOverloadCandidate(
FunTmpl, F.getPair(), ExplicitTemplateArgs,
{FunctionArgs[1], FunctionArgs[0]}, CandidateSet, false, false,
@@ -7730,11 +7849,11 @@ void Sema::AddNonMemberOperatorCandidates(
if (ExplicitTemplateArgs)
continue;
AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD))
- AddOverloadCandidate(FD, F.getPair(),
- {FunctionArgs[1], FunctionArgs[0]}, CandidateSet,
- false, false, true, false, ADLCallKind::NotADL,
- None, OverloadCandidateParamOrder::Reversed);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD))
+ AddOverloadCandidate(
+ FD, F.getPair(), {FunctionArgs[1], FunctionArgs[0]}, CandidateSet,
+ false, false, true, false, ADLCallKind::NotADL, std::nullopt,
+ OverloadCandidateParamOrder::Reversed);
}
}
}
@@ -7781,12 +7900,17 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
Operators.suppressDiagnostics();
for (LookupResult::iterator Oper = Operators.begin(),
- OperEnd = Operators.end();
- Oper != OperEnd;
- ++Oper)
+ OperEnd = Operators.end();
+ Oper != OperEnd; ++Oper) {
+ if (Oper->getAsFunction() &&
+ PO == OverloadCandidateParamOrder::Reversed &&
+ !CandidateSet.getRewriteInfo().shouldAddReversed(
+ *this, {Args[1], Args[0]}, Oper->getAsFunction()))
+ continue;
AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
Args[0]->Classify(Context), Args.slice(1),
CandidateSet, /*SuppressUserConversion=*/false, PO);
+ }
}
}
@@ -9312,7 +9436,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Plus: // '+' is either unary or binary
if (Args.size() == 1)
OpBuilder.addUnaryPlusPointerOverloads();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OO_Minus: // '-' is either unary or binary
if (Args.size() == 1) {
@@ -9387,12 +9511,12 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
case OO_Equal:
OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OO_PlusEqual:
case OO_MinusEqual:
OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OO_StarEqual:
case OO_SlashEqual:
@@ -9482,12 +9606,13 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
FD, FoundDecl, Args, CandidateSet, /*SuppressUserConversions=*/false,
PartialOverloading, /*AllowExplicit=*/true,
/*AllowExplicitConversion=*/false, ADLCallKind::UsesADL);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD)) {
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(*this, Args, FD)) {
AddOverloadCandidate(
FD, FoundDecl, {Args[1], Args[0]}, CandidateSet,
/*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit=*/true, /*AllowExplicitConversion=*/false,
- ADLCallKind::UsesADL, None, OverloadCandidateParamOrder::Reversed);
+ ADLCallKind::UsesADL, std::nullopt,
+ OverloadCandidateParamOrder::Reversed);
}
} else {
auto *FTD = cast<FunctionTemplateDecl>(*I);
@@ -9496,7 +9621,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
/*SuppressUserConversions=*/false, PartialOverloading,
/*AllowExplicit=*/true, ADLCallKind::UsesADL);
if (CandidateSet.getRewriteInfo().shouldAddReversed(
- Context, FTD->getTemplatedDecl())) {
+ *this, Args, FTD->getTemplatedDecl())) {
AddTemplateOverloadCandidate(
FTD, FoundDecl, ExplicitTemplateArgs, {Args[1], Args[0]},
CandidateSet, /*SuppressUserConversions=*/false, PartialOverloading,
@@ -9538,8 +9663,8 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
for (auto Pair : zip_longest(Cand1Attrs, Cand2Attrs)) {
- Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
- Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);
+ std::optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
+ std::optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);
// It's impossible for Cand1 to be better than (or equal to) Cand2 if Cand1
// has fewer enable_if attributes than Cand2, and vice versa.
@@ -9617,12 +9742,12 @@ isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
}
/// Compute the type of the implicit object parameter for the given function,
-/// if any. Returns None if there is no implicit object parameter, and a null
-/// QualType if there is a 'matches anything' implicit object parameter.
-static Optional<QualType> getImplicitObjectParamType(ASTContext &Context,
- const FunctionDecl *F) {
+/// if any. Returns std::nullopt if there is no implicit object parameter, and a
+/// null QualType if there is a 'matches anything' implicit object parameter.
+static std::optional<QualType>
+getImplicitObjectParamType(ASTContext &Context, const FunctionDecl *F) {
if (!isa<CXXMethodDecl>(F) || isa<CXXConstructorDecl>(F))
- return llvm::None;
+ return std::nullopt;
auto *M = cast<CXXMethodDecl>(F);
// Static member functions' object parameters match all types.
@@ -9642,7 +9767,7 @@ static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
auto NextParam = [&](const FunctionDecl *F, unsigned &I, bool First) {
if (First) {
- if (Optional<QualType> T = getImplicitObjectParamType(Context, F))
+ if (std::optional<QualType> T = getImplicitObjectParamType(Context, F))
return *T;
}
assert(I < F->getNumParams());
@@ -9662,19 +9787,13 @@ static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
/// We're allowed to use constraints partial ordering only if the candidates
/// have the same parameter types:
-/// [temp.func.order]p6.2.2 [...] or if the function parameters that
-/// positionally correspond between the two templates are not of the same type,
-/// neither template is more specialized than the other.
/// [over.match.best]p2.6
/// F1 and F2 are non-template functions with the same parameter-type-lists,
/// and F1 is more constrained than F2 [...]
-static bool canCompareFunctionConstraints(Sema &S,
+static bool sameFunctionParameterTypeLists(Sema &S,
const OverloadCandidate &Cand1,
const OverloadCandidate &Cand2) {
- // FIXME: Per P2113R0 we also need to compare the template parameter lists
- // when comparing template functions.
- if (Cand1.Function && Cand2.Function && Cand1.Function->hasPrototype() &&
- Cand2.Function->hasPrototype()) {
+ if (Cand1.Function && Cand2.Function) {
auto *PT1 = cast<FunctionProtoType>(Cand1.Function->getFunctionType());
auto *PT2 = cast<FunctionProtoType>(Cand2.Function->getFunctionType());
if (PT1->getNumParams() == PT2->getNumParams() &&
@@ -9767,7 +9886,7 @@ bool clang::isBetterOverloadCandidate(
}
}
- // C++ [over.match.best]p1:
+ // C++ [over.match.best]p1: (Changed in C++2b)
//
// -- if F is a static member function, ICS1(F) is defined such
// that ICS1(F) is neither better nor worse than ICS1(G) for
@@ -9917,22 +10036,28 @@ bool clang::isBetterOverloadCandidate(
isa<CXXConversionDecl>(Cand1.Function) ? TPOC_Conversion
: TPOC_Call,
Cand1.ExplicitCallArguments, Cand2.ExplicitCallArguments,
- Cand1.isReversed() ^ Cand2.isReversed(),
- canCompareFunctionConstraints(S, Cand1, Cand2)))
+ Cand1.isReversed() ^ Cand2.isReversed()))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
// -— F1 and F2 are non-template functions with the same
// parameter-type-lists, and F1 is more constrained than F2 [...],
if (!Cand1IsSpecialization && !Cand2IsSpecialization &&
- canCompareFunctionConstraints(S, Cand1, Cand2)) {
- Expr *RC1 = Cand1.Function->getTrailingRequiresClause();
- Expr *RC2 = Cand2.Function->getTrailingRequiresClause();
+ sameFunctionParameterTypeLists(S, Cand1, Cand2)) {
+ FunctionDecl *Function1 = Cand1.Function;
+ FunctionDecl *Function2 = Cand2.Function;
+ if (FunctionDecl *MF = Function1->getInstantiatedFromMemberFunction())
+ Function1 = MF;
+ if (FunctionDecl *MF = Function2->getInstantiatedFromMemberFunction())
+ Function2 = MF;
+
+ const Expr *RC1 = Function1->getTrailingRequiresClause();
+ const Expr *RC2 = Function2->getTrailingRequiresClause();
if (RC1 && RC2) {
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (S.IsAtLeastAsConstrained(Cand1.Function, {RC1}, Cand2.Function, {RC2},
+ if (S.IsAtLeastAsConstrained(Function1, RC1, Function2, RC2,
AtLeastAsConstrained1) ||
- S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function, {RC1},
+ S.IsAtLeastAsConstrained(Function2, RC2, Function1, RC1,
AtLeastAsConstrained2))
return false;
if (AtLeastAsConstrained1 != AtLeastAsConstrained2)
@@ -10103,6 +10228,13 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations(
}
}
+bool OverloadCandidate::NotValidBecauseConstraintExprHasError() const {
+ return FailureKind == ovl_fail_bad_deduction &&
+ DeductionFailure.Result == Sema::TDK_ConstraintsNotSatisfied &&
+ static_cast<CNSInfo *>(DeductionFailure.Data)
+ ->Satisfaction.ContainsErrors;
+}
+
/// Computes the best viable function (C++ 13.3.3)
/// within an overload candidate set.
///
@@ -10155,10 +10287,18 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
Best = end();
for (auto *Cand : Candidates) {
Cand->Best = false;
- if (Cand->Viable)
+ if (Cand->Viable) {
if (Best == end() ||
isBetterOverloadCandidate(S, *Cand, *Best, Loc, Kind))
Best = Cand;
+ } else if (Cand->NotValidBecauseConstraintExprHasError()) {
+ // This candidate has constraint that we were unable to evaluate because
+ // it referenced an expression that contained an error. Rather than fall
+ // back onto a potentially unintended candidate (made worse by
+ // subsuming constraints), treat this as 'no viable candidate'.
+ Best = end();
+ return OR_No_Viable_Function;
+ }
}
// If we didn't find any viable functions, abort.
@@ -10431,6 +10571,9 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
!Fn->getAttr<TargetAttr>()->isDefaultVersion())
return;
+ if (Fn->isMultiVersion() && Fn->hasAttr<TargetVersionAttr>() &&
+ !Fn->getAttr<TargetVersionAttr>()->isDefaultVersion())
+ return;
if (shouldSkipNotingLambdaConversionDecl(Fn))
return;
@@ -10774,10 +10917,13 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
<< ToTy << (unsigned)isObjectArgument << I + 1
<< (unsigned)(Cand->Fix.Kind);
- // If we can fix the conversion, suggest the FixIts.
- for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
- HE = Cand->Fix.Hints.end(); HI != HE; ++HI)
- FDiag << *HI;
+ // Check that location of Fn is not in system header.
+ if (!S.SourceMgr.isInSystemHeader(Fn->getLocation())) {
+ // If we can fix the conversion, suggest the FixIts.
+ for (const FixItHint &HI : Cand->Fix.Hints)
+ FDiag << HI;
+ }
+
S.Diag(Fn->getLocation(), FDiag);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
@@ -11483,6 +11629,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
switch ((Sema::TemplateDeductionResult)DFI.Result) {
case Sema::TDK_Success:
case Sema::TDK_NonDependentConversionFailure:
+ case Sema::TDK_AlreadyDiagnosed:
llvm_unreachable("non-deduction failure while diagnosing bad deduction");
case Sema::TDK_Invalid:
@@ -12239,6 +12386,9 @@ private:
const auto *TA = FunDecl->getAttr<TargetAttr>();
if (TA && !TA->isDefaultVersion())
return false;
+ const auto *TVA = FunDecl->getAttr<TargetVersionAttr>();
+ if (TVA && !TVA->isDefaultVersion())
+ return false;
}
// If any candidate has a placeholder return type, trigger its deduction
@@ -12501,20 +12651,24 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
DeclAccessPair DAP;
SmallVector<FunctionDecl *, 2> AmbiguousDecls;
- auto CheckMoreConstrained =
- [&] (FunctionDecl *FD1, FunctionDecl *FD2) -> Optional<bool> {
- SmallVector<const Expr *, 1> AC1, AC2;
- FD1->getAssociatedConstraints(AC1);
- FD2->getAssociatedConstraints(AC2);
- bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
- return None;
- if (IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
- return None;
- if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
- return None;
- return AtLeastAsConstrained1;
- };
+ auto CheckMoreConstrained = [&](FunctionDecl *FD1,
+ FunctionDecl *FD2) -> std::optional<bool> {
+ if (FunctionDecl *MF = FD1->getInstantiatedFromMemberFunction())
+ FD1 = MF;
+ if (FunctionDecl *MF = FD2->getInstantiatedFromMemberFunction())
+ FD2 = MF;
+ SmallVector<const Expr *, 1> AC1, AC2;
+ FD1->getAssociatedConstraints(AC1);
+ FD2->getAssociatedConstraints(AC2);
+ bool AtLeastAsConstrained1, AtLeastAsConstrained2;
+ if (IsAtLeastAsConstrained(FD1, AC1, FD2, AC2, AtLeastAsConstrained1))
+ return std::nullopt;
+ if (IsAtLeastAsConstrained(FD2, AC2, FD1, AC1, AtLeastAsConstrained2))
+ return std::nullopt;
+ if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
+ return std::nullopt;
+ return AtLeastAsConstrained1;
+ };
// Don't use the AddressOfResolver because we're specifically looking for
// cases where we have one overload candidate that lacks
@@ -12530,8 +12684,8 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
// We have more than one result - see if it is more constrained than the
// previous one.
if (Result) {
- Optional<bool> MoreConstrainedThanPrevious = CheckMoreConstrained(FD,
- Result);
+ std::optional<bool> MoreConstrainedThanPrevious =
+ CheckMoreConstrained(FD, Result);
if (!MoreConstrainedThanPrevious) {
IsResultAmbiguous = true;
AmbiguousDecls.push_back(FD);
@@ -12569,7 +12723,7 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
/// Returns false if resolveAddressOfSingleOverloadCandidate fails.
/// Otherwise, returns true. This may emit diagnostics and return true.
bool Sema::resolveAndFixAddressOfSingleOverloadCandidate(
- ExprResult &SrcExpr, bool DoFunctionPointerConverion) {
+ ExprResult &SrcExpr, bool DoFunctionPointerConversion) {
Expr *E = SrcExpr.get();
assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload");
@@ -12585,7 +12739,7 @@ bool Sema::resolveAndFixAddressOfSingleOverloadCandidate(
DiagnoseUseOfDecl(Found, E->getExprLoc());
CheckAddressOfMemberAccess(E, DAP);
Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found);
- if (DoFunctionPointerConverion && Fixed->getType()->isFunctionType())
+ if (DoFunctionPointerConversion && Fixed->getType()->isFunctionType())
SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false);
else
SrcExpr = Fixed;
@@ -12687,10 +12841,9 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// expression, regardless of whether or not it succeeded. Always
// returns true if 'complain' is set.
bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
- ExprResult &SrcExpr, bool doFunctionPointerConverion,
- bool complain, SourceRange OpRangeForComplaining,
- QualType DestTypeForComplaining,
- unsigned DiagIDForComplaining) {
+ ExprResult &SrcExpr, bool doFunctionPointerConversion, bool complain,
+ SourceRange OpRangeForComplaining, QualType DestTypeForComplaining,
+ unsigned DiagIDForComplaining) {
assert(SrcExpr.get()->getType() == Context.OverloadTy);
OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get());
@@ -12731,7 +12884,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
FixOverloadedFunctionReference(SrcExpr.get(), found, fn);
// If desired, do function-to-pointer decay.
- if (doFunctionPointerConverion) {
+ if (doFunctionPointerConversion) {
SingleFunctionExpression =
DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.get());
if (SingleFunctionExpression.isInvalid()) {
@@ -13008,17 +13161,16 @@ DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
namespace {
class BuildRecoveryCallExprRAII {
Sema &SemaRef;
+ Sema::SatisfactionStackResetRAII SatStack;
+
public:
- BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S) {
+ BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S), SatStack(S) {
assert(SemaRef.IsBuildingRecoveryCallExpr == false);
SemaRef.IsBuildingRecoveryCallExpr = true;
}
- ~BuildRecoveryCallExprRAII() {
- SemaRef.IsBuildingRecoveryCallExpr = false;
- }
+ ~BuildRecoveryCallExprRAII() { SemaRef.IsBuildingRecoveryCallExpr = false; }
};
-
}
/// Attempts to recover from a call where no functions were found.
@@ -13191,7 +13343,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// Guess at what the return type for an unresolvable overload should be.
static QualType chooseRecoveryType(OverloadCandidateSet &CS,
OverloadCandidateSet::iterator *Best) {
- llvm::Optional<QualType> Result;
+ std::optional<QualType> Result;
// Adjust Type after seeing a candidate.
auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) {
if (!Candidate.Function)
@@ -13594,14 +13746,14 @@ void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
- if (CandidateSet.getRewriteInfo().shouldAddReversed(Op))
+ if (CandidateSet.getRewriteInfo().allowsReversed(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))
+ if (CandidateSet.getRewriteInfo().allowsReversed(ExtraOp))
AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
CandidateSet,
OverloadCandidateParamOrder::Reversed);
@@ -13732,9 +13884,9 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
// Build the overload set.
- OverloadCandidateSet CandidateSet(
- OpLoc, OverloadCandidateSet::CSK_Operator,
- OverloadCandidateSet::OperatorRewriteInfo(Op, AllowRewrittenCandidates));
+ OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator,
+ OverloadCandidateSet::OperatorRewriteInfo(
+ Op, OpLoc, AllowRewrittenCandidates));
if (DefaultedFn)
CandidateSet.exclude(DefaultedFn);
LookupOverloadedBinOp(CandidateSet, Op, Fns, Args, PerformADL);
@@ -13809,6 +13961,22 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (AmbiguousWithSelf) {
Diag(FnDecl->getLocation(),
diag::note_ovl_ambiguous_oper_binary_reversed_self);
+ // Mark member== const or provide matching != to disallow reversed
+ // args. Eg.
+ // struct S { bool operator==(const S&); };
+ // S()==S();
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FnDecl))
+ if (Op == OverloadedOperatorKind::OO_EqualEqual &&
+ !MD->isConst() &&
+ Context.hasSameUnqualifiedType(
+ MD->getThisObjectType(),
+ MD->getParamDecl(0)->getType().getNonReferenceType()) &&
+ Context.hasSameUnqualifiedType(MD->getThisObjectType(),
+ Args[0]->getType()) &&
+ Context.hasSameUnqualifiedType(MD->getThisObjectType(),
+ Args[1]->getType()))
+ Diag(FnDecl->getLocation(),
+ diag::note_ovl_ambiguous_eqeq_reversed_self_non_const);
} else {
Diag(FnDecl->getLocation(),
diag::note_ovl_ambiguous_oper_binary_selected_candidate);
@@ -13932,7 +14100,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
R = CreateOverloadedBinOp(
OpLoc, Opc, Fns, IsReversed ? ZeroLiteral : R.get(),
- IsReversed ? R.get() : ZeroLiteral, PerformADL,
+ IsReversed ? R.get() : ZeroLiteral, /*PerformADL=*/true,
/*AllowRewrittenCandidates=*/false);
popCodeSynthesisContext();
@@ -14206,7 +14374,7 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
MultiExprArg ArgExpr) {
SmallVector<Expr *, 2> Args;
Args.push_back(Base);
- for (auto e : ArgExpr) {
+ for (auto *e : ArgExpr) {
Args.push_back(e);
}
DeclarationName OpName =
@@ -14271,12 +14439,17 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
SmallVector<Expr *, 2> MethodArgs;
- ExprResult Arg0 = PerformObjectArgumentInitialization(
- Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
- if (Arg0.isInvalid())
- return ExprError();
- MethodArgs.push_back(Arg0.get());
+ // Handle 'this' parameter if the selected function is not static.
+ if (Method->isInstance()) {
+ ExprResult Arg0 = PerformObjectArgumentInitialization(
+ Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ if (Arg0.isInvalid())
+ return ExprError();
+
+ MethodArgs.push_back(Arg0.get());
+ }
+
bool IsError = PrepareArgumentsForCallToObjectOfClassType(
*this, MethodArgs, Method, ArgExpr, LLoc);
if (IsError)
@@ -14296,9 +14469,16 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
- Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK, RLoc,
- CurFPFeatureOverrides());
+ CallExpr *TheCall;
+ if (Method->isInstance())
+ TheCall = CXXOperatorCallExpr::Create(
+ Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK,
+ RLoc, CurFPFeatureOverrides());
+ else
+ TheCall =
+ CallExpr::Create(Context, FnExpr.get(), MethodArgs, ResultTy, VK,
+ RLoc, CurFPFeatureOverrides());
+
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
@@ -14535,7 +14715,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Method = cast<CXXMethodDecl>(Best->Function);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
- if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
+ if (DiagnoseUseOfOverloadedDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
break;
// If FoundDecl is different from Method (such as if one is a template
// and the other a specialization), make sure DiagnoseUseOfDecl is
@@ -14544,7 +14724,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// DiagnoseUseOfDecl to accept both the FoundDecl and the decl
// being used.
if (Method != FoundDecl.getDecl() &&
- DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
+ DiagnoseUseOfOverloadedDecl(Method, UnresExpr->getNameLoc()))
break;
Succeeded = true;
break;
@@ -14874,15 +15054,18 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
bool IsError = false;
- // Initialize the implicit object parameter.
- ExprResult ObjRes =
- PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/nullptr,
- Best->FoundDecl, Method);
- if (ObjRes.isInvalid())
- IsError = true;
- else
- Object = ObjRes;
- MethodArgs.push_back(Object.get());
+ // Initialize the implicit object parameter if needed.
+ // Since C++2b, this could also be a call to a static call operator
+ // which we emit as a regular CallExpr.
+ if (Method->isInstance()) {
+ ExprResult ObjRes = PerformObjectArgumentInitialization(
+ Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+ if (ObjRes.isInvalid())
+ IsError = true;
+ else
+ Object = ObjRes;
+ MethodArgs.push_back(Object.get());
+ }
IsError |= PrepareArgumentsForCallToObjectOfClassType(
*this, MethodArgs, Method, Args, LParenLoc);
@@ -14908,9 +15091,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
- Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, VK, RParenLoc,
- CurFPFeatureOverrides());
+ CallExpr *TheCall;
+ if (Method->isInstance())
+ TheCall = CXXOperatorCallExpr::Create(Context, OO_Call, NewFn.get(),
+ MethodArgs, ResultTy, VK, RParenLoc,
+ CurFPFeatureOverrides());
+ else
+ TheCall = CallExpr::Create(Context, NewFn.get(), MethodArgs, ResultTy, VK,
+ RParenLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
@@ -14956,7 +15144,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
- None, CandidateSet, /*SuppressUserConversion=*/false);
+ std::nullopt, CandidateSet,
+ /*SuppressUserConversion=*/false);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
@@ -15105,8 +15294,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
ResultTy = ResultTy.getNonLValueExprType(Context);
UserDefinedLiteral *UDL = UserDefinedLiteral::Create(
- Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy,
- VK, LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides());
+ Context, Fn.get(), llvm::ArrayRef(ConvArgs, Args.size()), ResultTy, VK,
+ LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
@@ -15146,7 +15335,8 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
*CallExpr = ExprError();
return FRS_DiagnosticIssued;
}
- *CallExpr = BuildCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr);
+ *CallExpr =
+ BuildCallExpr(S, MemberRef.get(), Loc, std::nullopt, Loc, nullptr);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
return FRS_DiagnosticIssued;