summaryrefslogtreecommitdiff
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.cpp625
1 files changed, 398 insertions, 227 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 0fd932fac970..8635397f4806 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -10,10 +10,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Sema/Overload.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.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"
@@ -21,9 +21,11 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Overload.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
@@ -38,6 +40,8 @@
using namespace clang;
using namespace sema;
+using AllowedExplicit = Sema::AllowedExplicit;
+
static bool functionHasPassObjectSizeParams(const FunctionDecl *FD) {
return llvm::any_of(FD->parameters(), [](const ParmVarDecl *P) {
return P->hasAttr<PassObjectSizeAttr>();
@@ -91,10 +95,9 @@ static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
OverloadCandidateSet& Conversions,
- bool AllowExplicit,
+ AllowedExplicit AllowExplicit,
bool AllowObjCConversionOnExplicit);
-
static ImplicitConversionSequence::CompareKind
CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
@@ -229,7 +232,6 @@ bool StandardConversionSequence::isPointerConversionToBool() const {
getFromType()->isMemberPointerType() ||
getFromType()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
- getFromType()->isNullPtrType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@@ -327,9 +329,8 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
goto FloatingIntegralConversion;
if (FromType->isIntegralOrUnscopedEnumerationType())
goto IntegralConversion;
- // Boolean conversions can be from pointers and pointers to members
- // [conv.bool], and those aren't considered narrowing conversions.
- return NK_Not_Narrowing;
+ // -- from a pointer type or pointer-to-member type to bool, or
+ return NK_Type_Narrowing;
// -- from a floating-point type to an integer type, or
//
@@ -1317,7 +1318,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
static ImplicitConversionSequence
TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
- bool AllowExplicit,
+ AllowedExplicit AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion,
@@ -1420,7 +1421,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
static ImplicitConversionSequence
TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
- bool AllowExplicit,
+ AllowedExplicit AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion,
@@ -1475,13 +1476,12 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
ImplicitConversionSequence
Sema::TryImplicitConversion(Expr *From, QualType ToType,
bool SuppressUserConversions,
- bool AllowExplicit,
+ AllowedExplicit AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion) {
- return ::TryImplicitConversion(*this, From, ToType,
- SuppressUserConversions, AllowExplicit,
- InOverloadResolution, CStyle,
+ return ::TryImplicitConversion(*this, From, ToType, SuppressUserConversions,
+ AllowExplicit, InOverloadResolution, CStyle,
AllowObjCWritebackConversion,
/*AllowObjCConversionOnExplicit=*/false);
}
@@ -1514,10 +1514,10 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From->getType(), From);
ICS = ::TryImplicitConversion(*this, From, ToType,
/*SuppressUserConversions=*/false,
- AllowExplicit,
+ AllowExplicit ? AllowedExplicit::All
+ : AllowedExplicit::None,
/*InOverloadResolution=*/false,
- /*CStyle=*/false,
- AllowObjCWritebackConversion,
+ /*CStyle=*/false, AllowObjCWritebackConversion,
/*AllowObjCConversionOnExplicit=*/false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
@@ -1653,9 +1653,13 @@ static bool IsVectorConversion(Sema &S, QualType FromType,
// 1)vector types are equivalent AltiVec and GCC vector types
// 2)lax vector conversions are permitted and the vector types are of the
// same size
+ // 3)the destination type does not have the ARM MVE strict-polymorphism
+ // attribute, which inhibits lax vector conversion for overload resolution
+ // only
if (ToType->isVectorType() && FromType->isVectorType()) {
if (S.Context.areCompatibleVectorTypes(FromType, ToType) ||
- S.isLaxVectorConversion(FromType, ToType)) {
+ (S.isLaxVectorConversion(FromType, ToType) &&
+ !ToType->hasAttr(attr::ArmMveStrictPolymorphism))) {
ICK = ICK_Vector_Conversion;
return true;
}
@@ -1844,8 +1848,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
(FromType->isArithmeticType() ||
FromType->isAnyPointerType() ||
FromType->isBlockPointerType() ||
- FromType->isMemberPointerType() ||
- FromType->isNullPtrType())) {
+ FromType->isMemberPointerType())) {
// Boolean conversions (C++ 4.12).
SCS.Second = ICK_Boolean_Conversion;
FromType = S.Context.BoolTy;
@@ -1867,6 +1870,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
// FIXME: disable conversions between long double and __float128 if
// their representation is different until there is back end support
// We of course allow this conversion if long double is really double.
+
+ // Conversions between bfloat and other floats are not permitted.
+ if (FromType == S.Context.BFloat16Ty || ToType == S.Context.BFloat16Ty)
+ return false;
if (&S.Context.getFloatTypeSemantics(FromType) !=
&S.Context.getFloatTypeSemantics(ToType)) {
bool Float128AndLongDouble = ((FromType == S.Context.Float128Ty &&
@@ -1885,6 +1892,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
ToType->isIntegralType(S.Context)) ||
(FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isRealFloatingType())) {
+ // Conversions between bfloat and int are not permitted.
+ if (FromType->isBFloat16Type() || ToType->isBFloat16Type())
+ return false;
+
// Floating-integral conversions (C++ 4.9).
SCS.Second = ICK_Floating_Integral;
FromType = ToType.getUnqualifiedType();
@@ -3000,13 +3011,13 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
// We must have a derived-to-base conversion. Check an
// ambiguous or inaccessible conversion.
unsigned InaccessibleID = 0;
- unsigned AmbigiousID = 0;
+ unsigned AmbiguousID = 0;
if (Diagnose) {
InaccessibleID = diag::err_upcast_to_inaccessible_base;
- AmbigiousID = diag::err_ambiguous_derived_to_base_conv;
+ AmbiguousID = diag::err_ambiguous_derived_to_base_conv;
}
if (CheckDerivedToBaseConversion(
- FromPointeeType, ToPointeeType, InaccessibleID, AmbigiousID,
+ FromPointeeType, ToPointeeType, InaccessibleID, AmbiguousID,
From->getExprLoc(), From->getSourceRange(), DeclarationName(),
&BasePath, IgnoreBaseAccess))
return true;
@@ -3176,7 +3187,7 @@ static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
/// FromType and \p ToType is permissible, given knowledge about whether every
/// outer layer is const-qualified.
static bool isQualificationConversionStep(QualType FromType, QualType ToType,
- bool CStyle,
+ bool CStyle, bool IsTopLevel,
bool &PreviousToQualsIncludeConst,
bool &ObjCLifetimeConversion) {
Qualifiers FromQuals = FromType.getQualifiers();
@@ -3213,11 +3224,15 @@ static bool isQualificationConversionStep(QualType FromType, QualType ToType,
if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
return false;
- // For a C-style cast, just require the address spaces to overlap.
- // FIXME: Does "superset" also imply the representation of a pointer is the
- // same? We're assuming that it does here and in compatiblyIncludes.
- if (CStyle && !ToQuals.isAddressSpaceSupersetOf(FromQuals) &&
- !FromQuals.isAddressSpaceSupersetOf(ToQuals))
+ // If address spaces mismatch:
+ // - in top level it is only valid to convert to addr space that is a
+ // superset in all cases apart from C-style casts where we allow
+ // conversions between overlapping address spaces.
+ // - in non-top levels it is not a valid conversion.
+ if (ToQuals.getAddressSpace() != FromQuals.getAddressSpace() &&
+ (!IsTopLevel ||
+ !(ToQuals.isAddressSpaceSupersetOf(FromQuals) ||
+ (CStyle && FromQuals.isAddressSpaceSupersetOf(ToQuals)))))
return false;
// -- if the cv 1,j and cv 2,j are different, then const is in
@@ -3258,9 +3273,9 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
while (Context.UnwrapSimilarTypes(FromType, ToType)) {
- if (!isQualificationConversionStep(FromType, ToType, CStyle,
- PreviousToQualsIncludeConst,
- ObjCLifetimeConversion))
+ if (!isQualificationConversionStep(
+ FromType, ToType, CStyle, !UnwrappedAnyPointer,
+ PreviousToQualsIncludeConst, ObjCLifetimeConversion))
return false;
UnwrappedAnyPointer = true;
}
@@ -3393,9 +3408,10 @@ static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
- bool AllowExplicit,
+ AllowedExplicit AllowExplicit,
bool AllowObjCConversionOnExplicit) {
- assert(AllowExplicit || !AllowObjCConversionOnExplicit);
+ assert(AllowExplicit != AllowedExplicit::None ||
+ !AllowObjCConversionOnExplicit);
CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
// Whether we will only visit constructors.
@@ -3428,7 +3444,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) {
// But first, see if there is an init-list-constructor that will work.
OverloadingResult Result = IsInitializerListConstructorConversion(
- S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit);
+ S, From, ToType, ToRecordDecl, User, CandidateSet,
+ AllowExplicit == AllowedExplicit::All);
if (Result != OR_No_Viable_Function)
return Result;
// Never mind.
@@ -3467,14 +3484,16 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions,
- /*PartialOverloading*/ false, AllowExplicit);
+ /*PartialOverloading*/ false,
+ AllowExplicit == AllowedExplicit::All);
else
// 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,
- /*PartialOverloading*/ false, AllowExplicit);
+ /*PartialOverloading*/ false,
+ AllowExplicit == AllowedExplicit::All);
}
}
}
@@ -3507,11 +3526,12 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (ConvTemplate)
S.AddTemplateConversionCandidate(
ConvTemplate, FoundDecl, ActingContext, From, ToType,
- CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit);
+ CandidateSet, AllowObjCConversionOnExplicit,
+ AllowExplicit != AllowedExplicit::None);
else
- S.AddConversionCandidate(
- Conv, FoundDecl, ActingContext, From, ToType, CandidateSet,
- AllowObjCConversionOnExplicit, AllowExplicit);
+ S.AddConversionCandidate(Conv, FoundDecl, ActingContext, From, ToType,
+ CandidateSet, AllowObjCConversionOnExplicit,
+ AllowExplicit != AllowedExplicit::None);
}
}
}
@@ -3597,7 +3617,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
OverloadCandidateSet::CSK_Normal);
OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
- CandidateSet, false, false);
+ CandidateSet, AllowedExplicit::None, false);
if (!(OvResult == OR_Ambiguous ||
(OvResult == OR_No_Viable_Function && !CandidateSet.empty())))
@@ -4499,7 +4519,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc,
// If we find a qualifier mismatch, the types are not reference-compatible,
// but are still be reference-related if they're similar.
bool ObjCLifetimeConversion = false;
- if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false,
+ if (!isQualificationConversionStep(T2, T1, /*CStyle=*/false, TopLevel,
PreviousToQualsIncludeConst,
ObjCLifetimeConversion))
return (ConvertedReferent || Context.hasSimilarType(T1, T2))
@@ -4689,7 +4709,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
Sema::ReferenceConversions::NestedQualification)
? ICK_Qualification
: ICK_Identity;
- ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+ ICS.Standard.setFromType(T2);
ICS.Standard.setToType(0, T2);
ICS.Standard.setToType(1, T1);
ICS.Standard.setToType(2, T1);
@@ -4858,7 +4878,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
// cv-qualification is subsumed by the initialization itself
// and does not constitute a conversion.
ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
- /*AllowExplicit=*/false,
+ AllowedExplicit::None,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjCWritebackConversion=*/false,
@@ -5027,7 +5047,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
if (ToType->isRecordType() && !ToType->isAggregateType()) {
// This function can deal with initializer lists.
return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
- /*AllowExplicit=*/false,
+ AllowedExplicit::None,
InOverloadResolution, /*CStyle=*/false,
AllowObjCWritebackConversion,
/*AllowObjCConversionOnExplicit=*/false);
@@ -5179,7 +5199,7 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
return TryImplicitConversion(S, From, ToType,
SuppressUserConversions,
- /*AllowExplicit=*/false,
+ AllowedExplicit::None,
InOverloadResolution,
/*CStyle=*/false,
AllowObjCWritebackConversion,
@@ -5425,9 +5445,20 @@ Sema::PerformObjectArgumentInitialization(Expr *From,
/// expression From to bool (C++0x [conv]p3).
static ImplicitConversionSequence
TryContextuallyConvertToBool(Sema &S, Expr *From) {
+ // C++ [dcl.init]/17.8:
+ // - Otherwise, if the initialization is direct-initialization, the source
+ // type is std::nullptr_t, and the destination type is bool, the initial
+ // value of the object being initialized is false.
+ if (From->getType()->isNullPtrType())
+ return ImplicitConversionSequence::getNullptrToBool(From->getType(),
+ S.Context.BoolTy,
+ From->isGLValue());
+
+ // All other direct-initialization of bool is equivalent to an implicit
+ // conversion to bool in which explicit conversions are permitted.
return TryImplicitConversion(S, From, S.Context.BoolTy,
/*SuppressUserConversions=*/false,
- /*AllowExplicit=*/true,
+ AllowedExplicit::Conversions,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjCWritebackConversion=*/false,
@@ -5699,7 +5730,7 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
= TryImplicitConversion(S, From, Ty,
// FIXME: Are these flags correct?
/*SuppressUserConversions=*/false,
- /*AllowExplicit=*/true,
+ AllowedExplicit::Conversions,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjCWritebackConversion=*/false,
@@ -6291,9 +6322,9 @@ void Sema::AddOverloadCandidate(
return;
}
- if (Expr *RequiresClause = Function->getTrailingRequiresClause()) {
+ if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ if (CheckFunctionConstraints(Function, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -6333,7 +6364,8 @@ void Sema::AddOverloadCandidate(
}
}
- if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
+ if (EnableIfAttr *FailedAttr =
+ CheckEnableIf(Function, CandidateSet.getLocation(), Args)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -6439,11 +6471,10 @@ Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
return nullptr;
}
-static bool
-convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
- ArrayRef<Expr *> Args, Sema::SFINAETrap &Trap,
- bool MissingImplicitThis, Expr *&ConvertedThis,
- SmallVectorImpl<Expr *> &ConvertedArgs) {
+static bool convertArgsForAvailabilityChecks(
+ Sema &S, FunctionDecl *Function, Expr *ThisArg, SourceLocation CallLoc,
+ ArrayRef<Expr *> Args, Sema::SFINAETrap &Trap, bool MissingImplicitThis,
+ Expr *&ConvertedThis, SmallVectorImpl<Expr *> &ConvertedArgs) {
if (ThisArg) {
CXXMethodDecl *Method = cast<CXXMethodDecl>(Function);
assert(!isa<CXXConstructorDecl>(Method) &&
@@ -6488,17 +6519,9 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
ParmVarDecl *P = Function->getParamDecl(i);
- Expr *DefArg = P->hasUninstantiatedDefaultArg()
- ? P->getUninstantiatedDefaultArg()
- : P->getDefaultArg();
- // This can only happen in code completion, i.e. when PartialOverloading
- // is true.
- if (!DefArg)
+ if (!P->hasDefaultArg())
return false;
- ExprResult R =
- S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
- S.Context, Function->getParamDecl(i)),
- SourceLocation(), DefArg);
+ ExprResult R = S.BuildCXXDefaultArgExpr(CallLoc, Function, P);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
@@ -6510,7 +6533,9 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg,
return true;
}
-EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
+EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function,
+ SourceLocation CallLoc,
+ ArrayRef<Expr *> Args,
bool MissingImplicitThis) {
auto EnableIfAttrs = Function->specific_attrs<EnableIfAttr>();
if (EnableIfAttrs.begin() == EnableIfAttrs.end())
@@ -6521,7 +6546,7 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
// FIXME: We should look into making enable_if late-parsed.
Expr *DiscardedThis;
if (!convertArgsForAvailabilityChecks(
- *this, Function, /*ThisArg=*/nullptr, Args, Trap,
+ *this, Function, /*ThisArg=*/nullptr, CallLoc, Args, Trap,
/*MissingImplicitThis=*/true, DiscardedThis, ConvertedArgs))
return *EnableIfAttrs.begin();
@@ -6808,9 +6833,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
return;
}
- if (Expr *RequiresClause = Method->getTrailingRequiresClause()) {
+ if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ if (CheckFunctionConstraints(Method, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -6851,7 +6876,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
}
}
- if (EnableIfAttr *FailedAttr = CheckEnableIf(Method, Args, true)) {
+ if (EnableIfAttr *FailedAttr =
+ CheckEnableIf(Method, CandidateSet.getLocation(), Args, true)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -7204,10 +7230,9 @@ void Sema::AddConversionCandidate(
return;
}
- Expr *RequiresClause = Conversion->getTrailingRequiresClause();
- if (RequiresClause) {
+ if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (CheckConstraintSatisfaction(RequiresClause, Satisfaction) ||
+ if (CheckFunctionConstraints(Conversion, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
@@ -7305,7 +7330,8 @@ void Sema::AddConversionCandidate(
"Can only end up with a standard conversion sequence or failure");
}
- if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) {
+ if (EnableIfAttr *FailedAttr =
+ CheckEnableIf(Conversion, CandidateSet.getLocation(), None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -7475,7 +7501,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
}
}
- if (EnableIfAttr *FailedAttr = CheckEnableIf(Conversion, None)) {
+ if (EnableIfAttr *FailedAttr =
+ CheckEnableIf(Conversion, CandidateSet.getLocation(), None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
@@ -7665,6 +7692,10 @@ class BuiltinCandidateTypeSet {
/// candidates.
TypeSet VectorTypes;
+ /// The set of matrix types that will be used in the built-in
+ /// candidates.
+ TypeSet MatrixTypes;
+
/// A flag indicating non-record types are viable candidates
bool HasNonRecordTypes;
@@ -7722,9 +7753,11 @@ public:
/// enumeration_end - Past the last enumeration type found;
iterator enumeration_end() { return EnumerationTypes.end(); }
- iterator vector_begin() { return VectorTypes.begin(); }
- iterator vector_end() { return VectorTypes.end(); }
+ llvm::iterator_range<iterator> vector_types() { return VectorTypes; }
+
+ llvm::iterator_range<iterator> matrix_types() { return MatrixTypes; }
+ bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); }
bool hasNonRecordTypes() { return HasNonRecordTypes; }
bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; }
bool hasNullPtrType() const { return HasNullPtrType; }
@@ -7899,6 +7932,11 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
// extension.
HasArithmeticOrEnumeralTypes = true;
VectorTypes.insert(Ty);
+ } else if (Ty->isMatrixType()) {
+ // Similar to vector types, we treat vector types as arithmetic types in
+ // many contexts as an extension.
+ HasArithmeticOrEnumeralTypes = true;
+ MatrixTypes.insert(Ty);
} else if (Ty->isNullPtrType()) {
HasNullPtrType = true;
} else if (AllowUserConversions && TyRec) {
@@ -8127,6 +8165,13 @@ class BuiltinOperatorOverloadBuilder {
}
+ /// Helper to add an overload candidate for a binary builtin with types \p L
+ /// and \p R.
+ void AddCandidate(QualType L, QualType R) {
+ QualType LandR[2] = {L, R};
+ S.AddBuiltinCandidate(LandR, Args, CandidateSet);
+ }
+
public:
BuiltinOperatorOverloadBuilder(
Sema &S, ArrayRef<Expr *> Args,
@@ -8254,13 +8299,8 @@ public:
}
// Extension: We also add these operators for vector types.
- for (BuiltinCandidateTypeSet::iterator
- Vec = CandidateTypes[0].vector_begin(),
- VecEnd = CandidateTypes[0].vector_end();
- Vec != VecEnd; ++Vec) {
- QualType VecTy = *Vec;
+ for (QualType VecTy : CandidateTypes[0].vector_types())
S.AddBuiltinCandidate(&VecTy, Args, CandidateSet);
- }
}
// C++ [over.built]p8:
@@ -8294,13 +8334,8 @@ public:
}
// Extension: We also add this operator for vector types.
- for (BuiltinCandidateTypeSet::iterator
- Vec = CandidateTypes[0].vector_begin(),
- VecEnd = CandidateTypes[0].vector_end();
- Vec != VecEnd; ++Vec) {
- QualType VecTy = *Vec;
+ for (QualType VecTy : CandidateTypes[0].vector_types())
S.AddBuiltinCandidate(&VecTy, Args, CandidateSet);
- }
}
// C++ [over.match.oper]p16:
@@ -8380,7 +8415,7 @@ public:
// We interpret "same parameter-type-list" as applying to the
// "synthesized candidate, with the order of the two parameters
// reversed", not to the original function.
- bool Reversed = C->RewriteKind & CRK_Reversed;
+ bool Reversed = C->isReversed();
QualType FirstParamType = C->Function->getParamDecl(Reversed ? 1 : 0)
->getType()
.getUnqualifiedType();
@@ -8531,17 +8566,31 @@ public:
// Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the
// conditional operator for vector types.
- for (BuiltinCandidateTypeSet::iterator
- Vec1 = CandidateTypes[0].vector_begin(),
- Vec1End = CandidateTypes[0].vector_end();
- Vec1 != Vec1End; ++Vec1) {
- for (BuiltinCandidateTypeSet::iterator
- Vec2 = CandidateTypes[1].vector_begin(),
- Vec2End = CandidateTypes[1].vector_end();
- Vec2 != Vec2End; ++Vec2) {
- QualType LandR[2] = { *Vec1, *Vec2 };
+ for (QualType Vec1Ty : CandidateTypes[0].vector_types())
+ for (QualType Vec2Ty : CandidateTypes[1].vector_types()) {
+ QualType LandR[2] = {Vec1Ty, Vec2Ty};
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
+ }
+
+ /// Add binary operator overloads for each candidate matrix type M1, M2:
+ /// * (M1, M1) -> M1
+ /// * (M1, M1.getElementType()) -> M1
+ /// * (M2.getElementType(), M2) -> M2
+ /// * (M2, M2) -> M2 // Only if M2 is not part of CandidateTypes[0].
+ void addMatrixBinaryArithmeticOverloads() {
+ if (!HasArithmeticOrEnumeralCandidateType)
+ return;
+
+ for (QualType M1 : CandidateTypes[0].matrix_types()) {
+ AddCandidate(M1, cast<MatrixType>(M1)->getElementType());
+ AddCandidate(M1, M1);
+ }
+
+ for (QualType M2 : CandidateTypes[1].matrix_types()) {
+ AddCandidate(cast<MatrixType>(M2)->getElementType(), M2);
+ if (!CandidateTypes[0].containsMatrixType(M2))
+ AddCandidate(M2, M2);
}
}
@@ -8802,30 +8851,23 @@ public:
}
// Extension: Add the binary operators =, +=, -=, *=, /= for vector types.
- for (BuiltinCandidateTypeSet::iterator
- Vec1 = CandidateTypes[0].vector_begin(),
- Vec1End = CandidateTypes[0].vector_end();
- Vec1 != Vec1End; ++Vec1) {
- for (BuiltinCandidateTypeSet::iterator
- Vec2 = CandidateTypes[1].vector_begin(),
- Vec2End = CandidateTypes[1].vector_end();
- Vec2 != Vec2End; ++Vec2) {
+ for (QualType Vec1Ty : CandidateTypes[0].vector_types())
+ for (QualType Vec2Ty : CandidateTypes[0].vector_types()) {
QualType ParamTypes[2];
- ParamTypes[1] = *Vec2;
+ ParamTypes[1] = Vec2Ty;
// Add this built-in operator as a candidate (VQ is empty).
- ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1);
+ ParamTypes[0] = S.Context.getLValueReferenceType(Vec1Ty);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/isEqualOp);
// Add this built-in operator as a candidate (VQ is 'volatile').
if (VisibleTypeConversionsQuals.hasVolatile()) {
- ParamTypes[0] = S.Context.getVolatileType(*Vec1);
+ ParamTypes[0] = S.Context.getVolatileType(Vec1Ty);
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
/*IsAssignmentOperator=*/isEqualOp);
}
}
- }
}
// C++ [over.built]p22:
@@ -9118,14 +9160,17 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
} else {
OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
OpBuilder.addGenericBinaryArithmeticOverloads();
+ OpBuilder.addMatrixBinaryArithmeticOverloads();
}
break;
case OO_Star: // '*' is either unary or binary
if (Args.size() == 1)
OpBuilder.addUnaryStarPointerOverloads();
- else
+ else {
OpBuilder.addGenericBinaryArithmeticOverloads();
+ OpBuilder.addMatrixBinaryArithmeticOverloads();
+ }
break;
case OO_Slash:
@@ -9270,17 +9315,31 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
if (ExplicitTemplateArgs)
continue;
- AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet,
- /*SuppressUserConversions=*/false, PartialOverloading,
- /*AllowExplicit*/ true,
- /*AllowExplicitConversions*/ false,
- ADLCallKind::UsesADL);
+ AddOverloadCandidate(
+ FD, FoundDecl, Args, CandidateSet, /*SuppressUserConversions=*/false,
+ PartialOverloading, /*AllowExplicit=*/true,
+ /*AllowExplicitConversions=*/false, ADLCallKind::UsesADL);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD)) {
+ AddOverloadCandidate(
+ FD, FoundDecl, {Args[1], Args[0]}, CandidateSet,
+ /*SuppressUserConversions=*/false, PartialOverloading,
+ /*AllowExplicit=*/true, /*AllowExplicitConversions=*/false,
+ ADLCallKind::UsesADL, None, OverloadCandidateParamOrder::Reversed);
+ }
} else {
+ auto *FTD = cast<FunctionTemplateDecl>(*I);
AddTemplateOverloadCandidate(
- cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, Args,
- CandidateSet,
+ FTD, FoundDecl, ExplicitTemplateArgs, Args, CandidateSet,
/*SuppressUserConversions=*/false, PartialOverloading,
- /*AllowExplicit*/true, ADLCallKind::UsesADL);
+ /*AllowExplicit=*/true, ADLCallKind::UsesADL);
+ if (CandidateSet.getRewriteInfo().shouldAddReversed(
+ Context, FTD->getTemplatedDecl())) {
+ AddTemplateOverloadCandidate(
+ FTD, FoundDecl, ExplicitTemplateArgs, {Args[1], Args[0]},
+ CandidateSet, /*SuppressUserConversions=*/false, PartialOverloading,
+ /*AllowExplicit=*/true, ADLCallKind::UsesADL,
+ OverloadCandidateParamOrder::Reversed);
+ }
}
}
}
@@ -9338,16 +9397,22 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
return Comparison::Equal;
}
-static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
- const OverloadCandidate &Cand2) {
+static Comparison
+isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2) {
if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function ||
!Cand2.Function->isMultiVersion())
- return false;
+ return Comparison::Equal;
- // If Cand1 is invalid, it cannot be a better match, if Cand2 is invalid, this
- // is obviously better.
- if (Cand1.Function->isInvalidDecl()) return false;
- if (Cand2.Function->isInvalidDecl()) return true;
+ // If both are invalid, they are equal. If one of them is invalid, the other
+ // is better.
+ if (Cand1.Function->isInvalidDecl()) {
+ if (Cand2.Function->isInvalidDecl())
+ return Comparison::Equal;
+ return Comparison::Worse;
+ }
+ if (Cand2.Function->isInvalidDecl())
+ return Comparison::Better;
// If this is a cpu_dispatch/cpu_specific multiversion situation, prefer
// cpu_dispatch, else arbitrarily based on the identifiers.
@@ -9357,16 +9422,18 @@ static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>();
if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec)
- return false;
+ return Comparison::Equal;
if (Cand1CPUDisp && !Cand2CPUDisp)
- return true;
+ return Comparison::Better;
if (Cand2CPUDisp && !Cand1CPUDisp)
- return false;
+ return Comparison::Worse;
if (Cand1CPUSpec && Cand2CPUSpec) {
if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size())
- return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size();
+ return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size()
+ ? Comparison::Better
+ : Comparison::Worse;
std::pair<CPUSpecificAttr::cpus_iterator, CPUSpecificAttr::cpus_iterator>
FirstDiff = std::mismatch(
@@ -9379,11 +9446,56 @@ static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
assert(FirstDiff.first != Cand1CPUSpec->cpus_end() &&
"Two different cpu-specific versions should not have the same "
"identifier list, otherwise they'd be the same decl!");
- return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName();
+ return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName()
+ ? Comparison::Better
+ : Comparison::Worse;
}
llvm_unreachable("No way to get here unless both had cpu_dispatch");
}
+/// 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 (!isa<CXXMethodDecl>(F) || isa<CXXConstructorDecl>(F))
+ return llvm::None;
+
+ auto *M = cast<CXXMethodDecl>(F);
+ // Static member functions' object parameters match all types.
+ if (M->isStatic())
+ return QualType();
+
+ QualType T = M->getThisObjectType();
+ if (M->getRefQualifier() == RQ_RValue)
+ return Context.getRValueReferenceType(T);
+ return Context.getLValueReferenceType(T);
+}
+
+static bool haveSameParameterTypes(ASTContext &Context, const FunctionDecl *F1,
+ const FunctionDecl *F2, unsigned NumParams) {
+ if (declaresSameEntity(F1, F2))
+ return true;
+
+ auto NextParam = [&](const FunctionDecl *F, unsigned &I, bool First) {
+ if (First) {
+ if (Optional<QualType> T = getImplicitObjectParamType(Context, F))
+ return *T;
+ }
+ assert(I < F->getNumParams());
+ return F->getParamDecl(I++)->getType();
+ };
+
+ unsigned I1 = 0, I2 = 0;
+ for (unsigned I = 0; I != NumParams; ++I) {
+ QualType T1 = NextParam(F1, I1, I == 0);
+ QualType T2 = NextParam(F2, I2, I == 0);
+ if (!T1.isNull() && !T1.isNull() && !Context.hasSameUnqualifiedType(T1, T2))
+ return false;
+ }
+ return true;
+}
+
/// isBetterOverloadCandidate - Determines whether the first overload
/// candidate is a better candidate than the second (C++ 13.3.3p1).
bool clang::isBetterOverloadCandidate(
@@ -9451,18 +9563,20 @@ bool clang::isBetterOverloadCandidate(
break;
case ImplicitConversionSequence::Worse:
- if (Cand1.Function && Cand1.Function == Cand2.Function &&
- (Cand2.RewriteKind & CRK_Reversed) != 0) {
+ if (Cand1.Function && Cand2.Function &&
+ Cand1.isReversed() != Cand2.isReversed() &&
+ haveSameParameterTypes(S.Context, Cand1.Function, Cand2.Function,
+ NumArgs)) {
// Work around large-scale breakage caused by considering reversed
// forms of operator== in C++20:
//
- // When comparing a function against its reversed form, if we have a
- // better conversion for one argument and a worse conversion for the
- // other, we prefer the non-reversed form.
+ // When comparing a function against a reversed function with the same
+ // parameter types, if we have a better conversion for one argument and
+ // a worse conversion for the other, the implicit conversion sequences
+ // are treated as being equally good.
//
- // This prevents a conversion function from being considered ambiguous
- // with its own reversed form in various where it's only incidentally
- // heterogeneous.
+ // This prevents a comparison function from being considered ambiguous
+ // with a reversed form that is written in the same way.
//
// We diagnose this as an extension from CreateOverloadedBinOp.
HasWorseConversion = true;
@@ -9480,10 +9594,8 @@ bool clang::isBetterOverloadCandidate(
// -- for some argument j, ICSj(F1) is a better conversion sequence than
// ICSj(F2), or, if not that,
- if (HasBetterConversion)
+ if (HasBetterConversion && !HasWorseConversion)
return true;
- if (HasWorseConversion)
- return false;
// -- the context is an initialization by user-defined conversion
// (see 8.5, 13.3.1.5) and the standard conversion sequence
@@ -9540,14 +9652,13 @@ bool clang::isBetterOverloadCandidate(
// according to the partial ordering rules described in 14.5.5.2, or,
// if not that,
if (Cand1IsSpecialization && Cand2IsSpecialization) {
- if (FunctionTemplateDecl *BetterTemplate
- = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
- Cand2.Function->getPrimaryTemplate(),
- Loc,
- isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
- : TPOC_Call,
- Cand1.ExplicitCallArguments,
- Cand2.ExplicitCallArguments))
+ if (FunctionTemplateDecl *BetterTemplate = S.getMoreSpecializedTemplate(
+ Cand1.Function->getPrimaryTemplate(),
+ Cand2.Function->getPrimaryTemplate(), Loc,
+ isa<CXXConversionDecl>(Cand1.Function) ? TPOC_Conversion
+ : TPOC_Call,
+ Cand1.ExplicitCallArguments, Cand2.ExplicitCallArguments,
+ Cand1.isReversed() ^ Cand2.isReversed()))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
@@ -9566,17 +9677,15 @@ bool clang::isBetterOverloadCandidate(
if (RC1 && RC2) {
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
if (S.IsAtLeastAsConstrained(Cand1.Function, {RC1}, Cand2.Function,
- {RC2}, AtLeastAsConstrained1))
- return false;
- if (!AtLeastAsConstrained1)
- return false;
- if (S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function,
+ {RC2}, AtLeastAsConstrained1) ||
+ S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function,
{RC1}, AtLeastAsConstrained2))
return false;
- if (!AtLeastAsConstrained2)
- return true;
- } else if (RC1 || RC2)
+ if (AtLeastAsConstrained1 != AtLeastAsConstrained2)
+ return AtLeastAsConstrained1;
+ } else if (RC1 || RC2) {
return RC1 != nullptr;
+ }
}
}
@@ -9646,7 +9755,8 @@ bool clang::isBetterOverloadCandidate(
if (HasPS1 != HasPS2 && HasPS1)
return true;
- return isBetterMultiversionCandidate(Cand1, Cand2);
+ Comparison MV = isBetterMultiversionCandidate(Cand1, Cand2);
+ return MV == Comparison::Better;
}
/// Determine whether two declarations are "equivalent" for the purposes of
@@ -9947,9 +10057,9 @@ static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
return false;
}
- if (const Expr *RC = FD->getTrailingRequiresClause()) {
+ if (FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
- if (S.CheckConstraintSatisfaction(RC, Satisfaction))
+ if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
return false;
if (!Satisfaction.IsSatisfied) {
if (Complain) {
@@ -10974,8 +11084,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
<< FnDesc /* Ignored */;
ConstraintSatisfaction Satisfaction;
- if (S.CheckConstraintSatisfaction(Fn->getTrailingRequiresClause(),
- Satisfaction))
+ if (S.CheckFunctionConstraints(Fn, Satisfaction))
break;
S.DiagnoseUnsatisfiedConstraint(Satisfaction);
}
@@ -11275,7 +11384,7 @@ CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
unsigned ConvIdx = 0;
unsigned ArgIdx = 0;
ArrayRef<QualType> ParamTypes;
- bool Reversed = Cand->RewriteKind & CRK_Reversed;
+ bool Reversed = Cand->isReversed();
if (Cand->IsSurrogate) {
QualType ConvType
@@ -12688,9 +12797,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// base classes.
CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy,
VK_RValue, RParenLoc);
- CE->setTypeDependent(true);
- CE->setValueDependent(true);
- CE->setInstantiationDependent(true);
+ CE->markDependentForPostponedNameLookup();
*Result = CE;
return true;
}
@@ -12703,6 +12810,42 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
return false;
}
+// Guess at what the return type for an unresolvable overload should be.
+static QualType chooseRecoveryType(OverloadCandidateSet &CS,
+ OverloadCandidateSet::iterator *Best) {
+ llvm::Optional<QualType> Result;
+ // Adjust Type after seeing a candidate.
+ auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) {
+ if (!Candidate.Function)
+ return;
+ QualType T = Candidate.Function->getReturnType();
+ if (T.isNull())
+ return;
+ if (!Result)
+ Result = T;
+ else if (Result != T)
+ Result = QualType();
+ };
+
+ // Look for an unambiguous type from a progressively larger subset.
+ // e.g. if types disagree, but all *viable* overloads return int, choose int.
+ //
+ // First, consider only the best candidate.
+ if (Best && *Best != CS.end())
+ ConsiderCandidate(**Best);
+ // Next, consider only viable candidates.
+ if (!Result)
+ for (const auto &C : CS)
+ if (C.Viable)
+ ConsiderCandidate(C);
+ // Finally, consider all candidates.
+ if (!Result)
+ for (const auto &C : CS)
+ ConsiderCandidate(C);
+
+ return Result.getValueOr(QualType());
+}
+
/// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns
/// the completed call expression. If overload resolution fails, emits
/// diagnostics and returns ExprError()
@@ -12792,8 +12935,11 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
}
}
- // Overload resolution failed.
- return ExprError();
+ // Overload resolution failed, try to recover.
+ SmallVector<Expr *, 8> SubExprs = {Fn};
+ SubExprs.append(Args.begin(), Args.end());
+ return SemaRef.CreateRecoveryExpr(Fn->getBeginLoc(), RParenLoc, SubExprs,
+ chooseRecoveryType(*CandidateSet, Best));
}
static void markUnaddressableCandidatesUnviable(Sema &S,
@@ -12893,8 +13039,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (Input->isTypeDependent()) {
if (Fns.empty())
- return new (Context) UnaryOperator(Input, Opc, Context.DependentTy,
- VK_RValue, OK_Ordinary, OpLoc, false);
+ return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
+ VK_RValue, OK_Ordinary, OpLoc, false,
+ CurFPFeatureOverrides());
CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators
UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(
@@ -12902,7 +13049,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
/*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end());
return CXXOperatorCallExpr::Create(Context, Op, Fn, ArgsArray,
Context.DependentTy, VK_RValue, OpLoc,
- FPOptions());
+ CurFPFeatureOverrides());
}
// Build an empty overload set.
@@ -12976,7 +13123,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
Args[0] = Input;
CallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
- FPOptions(), Best->IsADLCandidate);
+ CurFPFeatureOverrides(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
@@ -12984,8 +13131,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
if (CheckFunctionCall(FnDecl, TheCall,
FnDecl->getType()->castAs<FunctionProtoType>()))
return ExprError();
-
- return MaybeBindToTemporary(TheCall);
+ return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), FnDecl);
} else {
// We matched a built-in operator. Convert the arguments, then
// break out so that we will build the appropriate built-in
@@ -13134,7 +13280,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Expr *Args[2] = { LHS, RHS };
LHS=RHS=nullptr; // Please use only Args instead of LHS/RHS couple
- if (!getLangOpts().CPlusPlus2a)
+ if (!getLangOpts().CPlusPlus20)
AllowRewrittenCandidates = false;
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
@@ -13146,14 +13292,13 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
if (Opc <= BO_Assign || Opc > BO_OrAssign)
- return new (Context) BinaryOperator(
- Args[0], Args[1], Opc, Context.DependentTy, VK_RValue, OK_Ordinary,
- OpLoc, FPFeatures);
-
- return new (Context) CompoundAssignOperator(
- Args[0], Args[1], Opc, Context.DependentTy, VK_LValue, OK_Ordinary,
- Context.DependentTy, Context.DependentTy, OpLoc,
- FPFeatures);
+ return BinaryOperator::Create(
+ Context, Args[0], Args[1], Opc, Context.DependentTy, VK_RValue,
+ OK_Ordinary, OpLoc, CurFPFeatureOverrides());
+ return CompoundAssignOperator::Create(
+ Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
+ OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
+ Context.DependentTy);
}
// FIXME: save results of ADL from here?
@@ -13166,7 +13311,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
/*ADL*/ PerformADL, IsOverloaded(Fns), Fns.begin(), Fns.end());
return CXXOperatorCallExpr::Create(Context, Op, Fn, Args,
Context.DependentTy, VK_RValue, OpLoc,
- FPFeatures);
+ CurFPFeatureOverrides());
}
// Always do placeholder-like conversions on the RHS.
@@ -13210,7 +13355,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// We found a built-in operator or an overloaded operator.
FunctionDecl *FnDecl = Best->Function;
- bool IsReversed = (Best->RewriteKind & CRK_Reversed);
+ bool IsReversed = Best->isReversed();
if (IsReversed)
std::swap(Args[0], Args[1]);
@@ -13227,36 +13372,56 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// resolution for an operator@, its return type shall be cv bool
if (Best->RewriteKind && ChosenOp == OO_EqualEqual &&
!FnDecl->getReturnType()->isBooleanType()) {
- Diag(OpLoc, diag::err_ovl_rewrite_equalequal_not_bool)
+ bool IsExtension =
+ FnDecl->getReturnType()->isIntegralOrUnscopedEnumerationType();
+ Diag(OpLoc, IsExtension ? diag::ext_ovl_rewrite_equalequal_not_bool
+ : diag::err_ovl_rewrite_equalequal_not_bool)
<< FnDecl->getReturnType() << BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
Diag(FnDecl->getLocation(), diag::note_declared_at);
- return ExprError();
+ if (!IsExtension)
+ return ExprError();
}
if (AllowRewrittenCandidates && !IsReversed &&
- CandidateSet.getRewriteInfo().shouldAddReversed(ChosenOp)) {
- // We could have reversed this operator, but didn't. Check if the
+ CandidateSet.getRewriteInfo().isReversible()) {
+ // We could have reversed this operator, but didn't. Check if some
// reversed form was a viable candidate, and if so, if it had a
// better conversion for either parameter. If so, this call is
// formally ambiguous, and allowing it is an extension.
+ llvm::SmallVector<FunctionDecl*, 4> AmbiguousWith;
for (OverloadCandidate &Cand : CandidateSet) {
- if (Cand.Viable && Cand.Function == FnDecl &&
- Cand.RewriteKind & CRK_Reversed) {
+ if (Cand.Viable && Cand.Function && Cand.isReversed() &&
+ haveSameParameterTypes(Context, Cand.Function, FnDecl, 2)) {
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
if (CompareImplicitConversionSequences(
*this, OpLoc, Cand.Conversions[ArgIdx],
Best->Conversions[ArgIdx]) ==
ImplicitConversionSequence::Better) {
- Diag(OpLoc, diag::ext_ovl_ambiguous_oper_binary_reversed)
- << BinaryOperator::getOpcodeStr(Opc)
- << Args[0]->getType() << Args[1]->getType()
- << Args[0]->getSourceRange() << Args[1]->getSourceRange();
- Diag(FnDecl->getLocation(),
- diag::note_ovl_ambiguous_oper_binary_reversed_candidate);
+ AmbiguousWith.push_back(Cand.Function);
+ break;
}
}
- break;
+ }
+ }
+
+ if (!AmbiguousWith.empty()) {
+ bool AmbiguousWithSelf =
+ AmbiguousWith.size() == 1 &&
+ declaresSameEntity(AmbiguousWith.front(), FnDecl);
+ Diag(OpLoc, diag::ext_ovl_ambiguous_oper_binary_reversed)
+ << BinaryOperator::getOpcodeStr(Opc)
+ << Args[0]->getType() << Args[1]->getType() << AmbiguousWithSelf
+ << Args[0]->getSourceRange() << Args[1]->getSourceRange();
+ if (AmbiguousWithSelf) {
+ Diag(FnDecl->getLocation(),
+ diag::note_ovl_ambiguous_oper_binary_reversed_self);
+ } else {
+ Diag(FnDecl->getLocation(),
+ diag::note_ovl_ambiguous_oper_binary_selected_candidate);
+ for (auto *F : AmbiguousWith)
+ Diag(F->getLocation(),
+ diag::note_ovl_ambiguous_oper_binary_reversed_candidate);
}
}
}
@@ -13315,7 +13480,7 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc,
- FPFeatures, Best->IsADLCandidate);
+ CurFPFeatureOverrides(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
@@ -13341,6 +13506,10 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
if (R.isInvalid())
return ExprError();
+ R = CheckForImmediateInvocation(R, FnDecl);
+ if (R.isInvalid())
+ return ExprError();
+
// For a rewritten candidate, we've already reversed the arguments
// if needed. Perform the rest of the rewrite now.
if ((Best->RewriteKind & CRK_DifferentOperator) ||
@@ -13580,10 +13749,10 @@ ExprResult Sema::BuildSynthesizedThreeWayComparison(
// Build a PseudoObjectExpr to model the rewriting of an <=> operator, and to
// bind the OpaqueValueExprs before they're (repeatedly) used.
- Expr *SyntacticForm = new (Context)
- BinaryOperator(OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
- Result.get()->getValueKind(),
- Result.get()->getObjectKind(), OpLoc, FPFeatures);
+ Expr *SyntacticForm = BinaryOperator::Create(
+ Context, OrigLHS, OrigRHS, BO_Cmp, Result.get()->getType(),
+ Result.get()->getValueKind(), Result.get()->getObjectKind(), OpLoc,
+ CurFPFeatureOverrides());
Expr *SemanticForm[] = {LHS, RHS, Result.get()};
return PseudoObjectExpr::Create(Context, SyntacticForm, SemanticForm, 2);
}
@@ -13614,7 +13783,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn, Args,
Context.DependentTy, VK_RValue, RLoc,
- FPOptions());
+ CurFPFeatureOverrides());
}
// Handle placeholders on both operands.
@@ -13687,10 +13856,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall =
- CXXOperatorCallExpr::Create(Context, OO_Subscript, FnExpr.get(),
- Args, ResultTy, VK, RLoc, FPOptions());
-
+ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, OO_Subscript, FnExpr.get(), Args, ResultTy, VK, RLoc,
+ CurFPFeatureOverrides());
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
@@ -14000,7 +14168,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// resolution process, we still need to handle the enable_if attribute. Do
// that here, so it will not hide previous -- and more relevant -- errors.
if (auto *MemE = dyn_cast<MemberExpr>(NakedMemExpr)) {
- if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
+ if (const EnableIfAttr *Attr =
+ CheckEnableIf(Method, LParenLoc, Args, true)) {
Diag(MemE->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< Method << Method->getSourceRange();
@@ -14039,7 +14208,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
MemExpr->getMemberLoc());
}
- return MaybeBindToTemporary(TheCall);
+ return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall),
+ TheCall->getMethodDecl());
}
/// BuildCallToObjectOfClassType - Build a call to an object of class
@@ -14310,9 +14480,9 @@ 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, FPOptions());
+ CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
+ Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, VK, RParenLoc,
+ CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
@@ -14320,7 +14490,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
if (CheckFunctionCall(Method, TheCall, Proto))
return true;
- return MaybeBindToTemporary(TheCall);
+ return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
}
/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator->
@@ -14428,8 +14598,9 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
- CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
- Context, OO_Arrow, FnExpr.get(), Base, ResultTy, VK, OpLoc, FPOptions());
+ CXXOperatorCallExpr *TheCall =
+ CXXOperatorCallExpr::Create(Context, OO_Arrow, FnExpr.get(), Base,
+ ResultTy, VK, OpLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
@@ -14515,7 +14686,7 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
if (CheckFunctionCall(FD, UDL, nullptr))
return ExprError();
- return MaybeBindToTemporary(UDL);
+ return CheckForImmediateInvocation(MaybeBindToTemporary(UDL), FD);
}
/// Build a call to 'begin' or 'end' for a C++11 for-range statement. If the
@@ -14676,9 +14847,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
- return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
- VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc(), false);
+ return UnaryOperator::Create(
+ Context, SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary,
+ UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
@@ -14686,10 +14857,10 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
if (SubExpr == UnOp->getSubExpr())
return UnOp;
- return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
- Context.getPointerType(SubExpr->getType()),
- VK_RValue, OK_Ordinary,
- UnOp->getOperatorLoc(), false);
+ return UnaryOperator::Create(Context, SubExpr, UO_AddrOf,
+ Context.getPointerType(SubExpr->getType()),
+ VK_RValue, OK_Ordinary, UnOp->getOperatorLoc(),
+ false, CurFPFeatureOverrides());
}
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {