#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"
#include "clang/AST/TypeOrdering.h"
#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"
#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 <algorithm>
#include <cstdlib>
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>();
});
}
static ExprResult CreateFunctionRefExpr(
Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, const Expr *Base,
bool HadMultipleCandidates, SourceLocation Loc = SourceLocation(),
const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) {
if (S.DiagnoseUseOfDecl(FoundDecl, Loc))
return ExprError();
if (FoundDecl != Fn && S.DiagnoseUseOfDecl(Fn, Loc))
return ExprError();
DeclRefExpr *DRE = new (S.Context)
DeclRefExpr(S.Context, Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
S.MarkDeclRefReferenced(DRE, Base);
if (auto *FPT = DRE->getType()->getAs<FunctionProtoType>()) {
if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
S.ResolveExceptionSpec(Loc, FPT);
DRE->setType(Fn->getType());
}
}
return S.ImpCastExprToType(DRE, S.Context.getPointerType(DRE->getType()),
CK_FunctionToPointerDecay);
}
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle,
bool AllowObjCWritebackConversion);
static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From,
QualType &ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle);
static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
OverloadCandidateSet& Conversions,
AllowedExplicit AllowExplicit,
bool AllowObjCConversionOnExplicit);
static ImplicitConversionSequence::CompareKind
CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
static ImplicitConversionSequence::CompareKind
CompareQualificationConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
static ImplicitConversionSequence::CompareKind
CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
static const ImplicitConversionRank
Rank[(int)ICK_Num_Conversion_Kinds] = {
ICR_Exact_Match,
ICR_Exact_Match,
ICR_Exact_Match,
ICR_Exact_Match,
ICR_Exact_Match,
ICR_Exact_Match,
ICR_Promotion,
ICR_Promotion,
ICR_Promotion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_OCL_Scalar_Widening,
ICR_Complex_Real_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Writeback_Conversion,
ICR_Exact_Match, ICR_C_Conversion,
ICR_C_Conversion_Extension
};
return Rank[(int)Kind];
}
static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
static const char* const Name[(int)ICK_Num_Conversion_Kinds] = {
"No conversion",
"Lvalue-to-rvalue",
"Array-to-pointer",
"Function-to-pointer",
"Function pointer conversion",
"Qualification",
"Integral promotion",
"Floating point promotion",
"Complex promotion",
"Integral conversion",
"Floating conversion",
"Complex conversion",
"Floating-integral conversion",
"Pointer conversion",
"Pointer-to-member conversion",
"Boolean conversion",
"Compatible-types conversion",
"Derived-to-base conversion",
"Vector conversion",
"SVE Vector conversion",
"Vector splat",
"Complex-real conversion",
"Block Pointer conversion",
"Transparent Union Conversion",
"Writeback conversion",
"OpenCL Zero Event Conversion",
"C specific type conversion",
"Incompatible pointer conversion"
};
return Name[Kind];
}
void StandardConversionSequence::setAsIdentityConversion() {
First = ICK_Identity;
Second = ICK_Identity;
Third = ICK_Identity;
DeprecatedStringLiteralToCharPtr = false;
QualificationIncludesObjCLifetime = false;
ReferenceBinding = false;
DirectBinding = false;
IsLvalueReference = true;
BindsToFunctionLvalue = false;
BindsToRvalue = false;
BindsImplicitObjectArgumentWithoutRefQualifier = false;
ObjCLifetimeConversionBinding = false;
CopyConstructor = nullptr;
}
ImplicitConversionRank StandardConversionSequence::getRank() const {
ImplicitConversionRank Rank = ICR_Exact_Match;
if (GetConversionRank(First) > Rank)
Rank = GetConversionRank(First);
if (GetConversionRank(Second) > Rank)
Rank = GetConversionRank(Second);
if (GetConversionRank(Third) > Rank)
Rank = GetConversionRank(Third);
return Rank;
}
bool StandardConversionSequence::isPointerConversionToBool() const {
if (getToType(1)->isBooleanType() &&
(getFromType()->isPointerType() ||
getFromType()->isMemberPointerType() ||
getFromType()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
return false;
}
bool
StandardConversionSequence::
isPointerConversionToVoidPointer(ASTContext& Context) const {
QualType FromType = getFromType();
QualType ToType = getToType(1);
if (First == ICK_Array_To_Pointer)
FromType = Context.getArrayDecayedType(FromType);
if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType())
if (const PointerType* ToPtrType = ToType->getAs<PointerType>())
return ToPtrType->getPointeeType()->isVoidType();
return false;
}
static const Expr *IgnoreNarrowingConversion(ASTContext &Ctx,
const Expr *Converted) {
if (auto *EWC = dyn_cast<ExprWithCleanups>(Converted)) {
Expr *Inner =
const_cast<Expr *>(IgnoreNarrowingConversion(Ctx, EWC->getSubExpr()));
return ExprWithCleanups::Create(Ctx, Inner, EWC->cleanupsHaveSideEffects(),
EWC->getObjects());
}
while (auto *ICE = dyn_cast<ImplicitCastExpr>(Converted)) {
switch (ICE->getCastKind()) {
case CK_NoOp:
case CK_IntegralCast:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_BooleanToSignedIntegral:
case CK_FloatingToIntegral:
case CK_FloatingToBoolean:
case CK_FloatingCast:
Converted = ICE->getSubExpr();
continue;
default:
return Converted;
}
}
return Converted;
}
NarrowingKind StandardConversionSequence::getNarrowingKind(
ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue,
QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const {
assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
QualType FromType = getToType(0);
QualType ToType = getToType(1);
if (auto *ET = ToType->getAs<EnumType>())
ToType = ET->getDecl()->getIntegerType();
switch (Second) {
case ICK_Boolean_Conversion:
if (FromType->isRealFloatingType())
goto FloatingIntegralConversion;
if (FromType->isIntegralOrUnscopedEnumerationType())
goto IntegralConversion;
return NK_Type_Narrowing;
case ICK_Floating_Integral:
FloatingIntegralConversion:
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
return NK_Type_Narrowing;
} else if (FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isRealFloatingType()) {
if (IgnoreFloatToIntegralConversion)
return NK_Not_Narrowing;
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
assert(Initializer && "Unknown conversion expression");
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
if (Optional<llvm::APSInt> IntConstantValue =
Initializer->getIntegerConstantExpr(Ctx)) {
llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType));
Result.convertFromAPInt(*IntConstantValue, IntConstantValue->isSigned(),
llvm::APFloat::rmNearestTiesToEven);
llvm::APSInt ConvertedValue = *IntConstantValue;
bool ignored;
Result.convertToInteger(ConvertedValue,
llvm::APFloat::rmTowardZero, &ignored);
if (*IntConstantValue != ConvertedValue) {
ConstantValue = APValue(*IntConstantValue);
ConstantType = Initializer->getType();
return NK_Constant_Narrowing;
}
} else {
return NK_Variable_Narrowing;
}
}
return NK_Not_Narrowing;
case ICK_Floating_Conversion:
if (FromType->isRealFloatingType() && ToType->isRealFloatingType() &&
Ctx.getFloatingTypeOrder(FromType, ToType) == 1) {
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) {
assert(ConstantValue.isFloat());
llvm::APFloat FloatVal = ConstantValue.getFloat();
bool ignored;
llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
Ctx.getFloatTypeSemantics(ToType),
llvm::APFloat::rmNearestTiesToEven, &ignored);
if (ConvertStatus & llvm::APFloat::opOverflow) {
ConstantType = Initializer->getType();
return NK_Constant_Narrowing;
}
} else {
return NK_Variable_Narrowing;
}
}
return NK_Not_Narrowing;
case ICK_Integral_Conversion:
IntegralConversion: {
assert(FromType->isIntegralOrUnscopedEnumerationType());
assert(ToType->isIntegralOrUnscopedEnumerationType());
const bool FromSigned = FromType->isSignedIntegerOrEnumerationType();
const unsigned FromWidth = Ctx.getIntWidth(FromType);
const bool ToSigned = ToType->isSignedIntegerOrEnumerationType();
const unsigned ToWidth = Ctx.getIntWidth(ToType);
if (FromWidth > ToWidth ||
(FromWidth == ToWidth && FromSigned != ToSigned) ||
(FromSigned && !ToSigned)) {
const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
if (Initializer->isValueDependent())
return NK_Dependent_Narrowing;
Optional<llvm::APSInt> OptInitializerValue;
if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) {
return NK_Variable_Narrowing;
}
llvm::APSInt &InitializerValue = *OptInitializerValue;
bool Narrowing = false;
if (FromWidth < ToWidth) {
if (InitializerValue.isSigned() && InitializerValue.isNegative())
Narrowing = true;
} else {
InitializerValue = InitializerValue.extend(
InitializerValue.getBitWidth() + 1);
llvm::APSInt ConvertedValue = InitializerValue;
ConvertedValue = ConvertedValue.trunc(ToWidth);
ConvertedValue.setIsSigned(ToSigned);
ConvertedValue = ConvertedValue.extend(InitializerValue.getBitWidth());
ConvertedValue.setIsSigned(InitializerValue.isSigned());
if (ConvertedValue != InitializerValue)
Narrowing = true;
}
if (Narrowing) {
ConstantType = Initializer->getType();
ConstantValue = APValue(InitializerValue);
return NK_Constant_Narrowing;
}
}
return NK_Not_Narrowing;
}
default:
return NK_Not_Narrowing;
}
}
LLVM_DUMP_METHOD void StandardConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
bool PrintedSomething = false;
if (First != ICK_Identity) {
OS << GetImplicitConversionName(First);
PrintedSomething = true;
}
if (Second != ICK_Identity) {
if (PrintedSomething) {
OS << " -> ";
}
OS << GetImplicitConversionName(Second);
if (CopyConstructor) {
OS << " (by copy constructor)";
} else if (DirectBinding) {
OS << " (direct reference binding)";
} else if (ReferenceBinding) {
OS << " (reference binding)";
}
PrintedSomething = true;
}
if (Third != ICK_Identity) {
if (PrintedSomething) {
OS << " -> ";
}
OS << GetImplicitConversionName(Third);
PrintedSomething = true;
}
if (!PrintedSomething) {
OS << "No conversions required";
}
}
void UserDefinedConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
if (Before.First || Before.Second || Before.Third) {
Before.dump();
OS << " -> ";
}
if (ConversionFunction)
OS << '\'' << *ConversionFunction << '\'';
else
OS << "aggregate initialization";
if (After.First || After.Second || After.Third) {
OS << " -> ";
After.dump();
}
}
void ImplicitConversionSequence::dump() const {
raw_ostream &OS = llvm::errs();
if (hasInitializerListContainerType())
OS << "Worst list element conversion: ";
switch (ConversionKind) {
case StandardConversion:
OS << "Standard conversion: ";
Standard.dump();
break;
case UserDefinedConversion:
OS << "User-defined conversion: ";
UserDefined.dump();
break;
case EllipsisConversion:
OS << "Ellipsis conversion";
break;
case AmbiguousConversion:
OS << "Ambiguous conversion";
break;
case BadConversion:
OS << "Bad conversion";
break;
}
OS << "\n";
}
void AmbiguousConversionSequence::construct() {
new (&conversions()) ConversionSet();
}
void AmbiguousConversionSequence::destruct() {
conversions().~ConversionSet();
}
void
AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
FromTypePtr = O.FromTypePtr;
ToTypePtr = O.ToTypePtr;
new (&conversions()) ConversionSet(O.conversions());
}
namespace {
struct DFIArguments {
TemplateArgument FirstArg;
TemplateArgument SecondArg;
};
struct DFIParamWithArguments : DFIArguments {
TemplateParameter Param;
};
struct DFIDeducedMismatchArgs : DFIArguments {
TemplateArgumentList *TemplateArgs;
unsigned CallArgIndex;
};
struct CNSInfo {
TemplateArgumentList *TemplateArgs;
ConstraintSatisfaction Satisfaction;
};
}
DeductionFailureInfo
clang::MakeDeductionFailureInfo(ASTContext &Context,
Sema::TemplateDeductionResult TDK,
TemplateDeductionInfo &Info) {
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
switch (TDK) {
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_MiscellaneousDeductionFailure:
case Sema::TDK_CUDATargetMismatch:
Result.Data = nullptr;
break;
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
Result.Data = Info.Param.getOpaqueValue();
break;
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested: {
auto *Saved = new (Context) DFIDeducedMismatchArgs;
Saved->FirstArg = Info.FirstArg;
Saved->SecondArg = Info.SecondArg;
Saved->TemplateArgs = Info.take();
Saved->CallArgIndex = Info.CallArgIndex;
Result.Data = Saved;
break;
}
case Sema::TDK_NonDeducedMismatch: {
DFIArguments *Saved = new (Context) DFIArguments;
Saved->FirstArg = Info.FirstArg;
Saved->SecondArg = Info.SecondArg;
Result.Data = Saved;
break;
}
case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified: {
DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments;
Saved->Param = Info.Param;
Saved->FirstArg = Info.FirstArg;
Saved->SecondArg = Info.SecondArg;
Result.Data = Saved;
break;
}
case Sema::TDK_SubstitutionFailure:
Result.Data = Info.take();
if (Info.hasSFINAEDiagnostic()) {
PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt(
SourceLocation(), PartialDiagnostic::NullDiagnostic());
Info.takeSFINAEDiagnostic(*Diag);
Result.HasDiagnostic = true;
}
break;
case Sema::TDK_ConstraintsNotSatisfied: {
CNSInfo *Saved = new (Context) CNSInfo;
Saved->TemplateArgs = Info.take();
Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction;
Result.Data = Saved;
break;
}
case Sema::TDK_Success:
case Sema::TDK_NonDependentConversionFailure:
llvm_unreachable("not a deduction failure");
}
return Result;
}
void DeductionFailureInfo::Destroy() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_Incomplete:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
break;
case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
Data = nullptr;
break;
case Sema::TDK_SubstitutionFailure:
Data = nullptr;
if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
Diag->~PartialDiagnosticAt();
HasDiagnostic = false;
}
break;
case Sema::TDK_ConstraintsNotSatisfied:
Data = nullptr;
if (PartialDiagnosticAt *Diag = getSFINAEDiagnostic()) {
Diag->~PartialDiagnosticAt();
HasDiagnostic = false;
}
break;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
}
PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
if (HasDiagnostic)
return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
return nullptr;
}
TemplateParameter DeductionFailureInfo::getTemplateParameter() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
case Sema::TDK_ConstraintsNotSatisfied:
return TemplateParameter();
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
return static_cast<DFIParamWithArguments*>(Data)->Param;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return TemplateParameter();
}
TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_Incomplete:
case Sema::TDK_IncompletePack:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
return nullptr;
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested:
return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
case Sema::TDK_ConstraintsNotSatisfied:
return static_cast<CNSInfo*>(Data)->TemplateArgs;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return nullptr;
}
const TemplateArgument *DeductionFailureInfo::getFirstArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_Incomplete:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
case Sema::TDK_ConstraintsNotSatisfied:
return nullptr;
case Sema::TDK_IncompletePack:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->FirstArg;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return nullptr;
}
const TemplateArgument *DeductionFailureInfo::getSecondArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_Incomplete:
case Sema::TDK_IncompletePack:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_CUDATargetMismatch:
case Sema::TDK_NonDependentConversionFailure:
case Sema::TDK_ConstraintsNotSatisfied:
return nullptr;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->SecondArg;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return nullptr;
}
llvm::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;
}
}
bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed(
OverloadedOperatorKind Op) {
if (!AllowRewrittenCandidates)
return false;
return Op == OO_EqualEqual || Op == OO_Spaceship;
}
bool OverloadCandidateSet::OperatorRewriteInfo::shouldAddReversed(
ASTContext &Ctx, const FunctionDecl *FD) {
if (!shouldAddReversed(FD->getDeclName().getCXXOverloadedOperator()))
return false;
return FD->getNumParams() != 2 ||
!Ctx.hasSameUnqualifiedType(FD->getParamDecl(0)->getType(),
FD->getParamDecl(1)->getType()) ||
FD->hasAttr<EnableIfAttr>();
}
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
for (auto &C : i->Conversions)
C.~ImplicitConversionSequence();
if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction)
i->DeductionFailure.Destroy();
}
}
void OverloadCandidateSet::clear(CandidateSetKind CSK) {
destroyCandidates();
SlabAllocator.Reset();
NumInlineBytesUsed = 0;
Candidates.clear();
Functions.clear();
Kind = CSK;
}
namespace {
class UnbridgedCastsSet {
struct Entry {
Expr **Addr;
Expr *Saved;
};
SmallVector<Entry, 2> Entries;
public:
void save(Sema &S, Expr *&E) {
assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
Entry entry = { &E, E };
Entries.push_back(entry);
E = S.stripARCUnbridgedCast(E);
}
void restore() {
for (SmallVectorImpl<Entry>::iterator
i = Entries.begin(), e = Entries.end(); i != e; ++i)
*i->Addr = i->Saved;
}
};
}
static bool
checkPlaceholderForOverload(Sema &S, Expr *&E,
UnbridgedCastsSet *unbridgedCasts = nullptr) {
if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) {
if (placeholder->getKind() == BuiltinType::Overload) return false;
if (placeholder->getKind() == BuiltinType::ARCUnbridgedCast &&
unbridgedCasts) {
unbridgedCasts->save(S, E);
return false;
}
ExprResult result = S.CheckPlaceholderExpr(E);
if (result.isInvalid())
return true;
E = result.get();
return false;
}
return false;
}
static bool checkArgPlaceholdersForOverload(Sema &S, MultiExprArg Args,
UnbridgedCastsSet &unbridged) {
for (unsigned i = 0, e = Args.size(); i != e; ++i)
if (checkPlaceholderForOverload(S, Args[i], &unbridged))
return true;
return false;
}
Sema::OverloadKind
Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
NamedDecl *&Match, bool NewIsUsingDecl) {
for (LookupResult::iterator I = Old.begin(), E = Old.end();
I != E; ++I) {
NamedDecl *OldD = *I;
bool OldIsUsingDecl = false;
if (isa<UsingShadowDecl>(OldD)) {
OldIsUsingDecl = true;
if (NewIsUsingDecl) continue;
OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl();
}
if ((OldIsUsingDecl || NewIsUsingDecl) && !isVisible(*I))
continue;
bool UseMemberUsingDeclRules =
(OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
!New->getFriendObjectKind();
if (FunctionDecl *OldF = OldD->getAsFunction()) {
if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
if (UseMemberUsingDeclRules && OldIsUsingDecl) {
HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
continue;
}
if (!isa<FunctionTemplateDecl>(OldD) &&
!shouldLinkPossiblyHiddenDecl(*I, New))
continue;
Match = *I;
return Ovl_Match;
}
if (!getASTContext().canBuiltinBeRedeclared(OldF)) {
Match = *I;
return Ovl_NonFunction;
}
} else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) {
assert(Old.getLookupKind() == LookupUsingDeclName);
} else if (isa<TagDecl>(OldD)) {
} else if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(OldD)) {
if (UUD->getQualifier()->isDependent() && !UUD->isCXXClassMember()) {
Match = *I;
return Ovl_NonFunction;
}
} else {
Match = *I;
return Ovl_NonFunction;
}
}
if (New->getFriendObjectKind() && New->getQualifier() &&
!New->getDescribedFunctionTemplate() &&
!New->getDependentSpecializationInfo() &&
!New->getType()->isDependentType()) {
LookupResult TemplateSpecResult(LookupResult::Temporary, Old);
TemplateSpecResult.addAllDecls(Old);
if (CheckFunctionTemplateSpecialization(New, nullptr, TemplateSpecResult,
true)) {
New->setInvalidDecl();
return Ovl_Overload;
}
Match = TemplateSpecResult.getAsSingle<FunctionDecl>();
return Ovl_Match;
}
return Ovl_Overload;
}
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs,
bool ConsiderRequiresClauses) {
if (New->isMain())
return false;
if (New->isMSVCRTEntryPoint())
return false;
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
if ((OldTemplate == nullptr) != (NewTemplate == nullptr))
return true;
QualType OldQType = Context.getCanonicalType(Old->getType());
QualType NewQType = Context.getCanonicalType(New->getType());
if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
isa<FunctionNoProtoType>(NewQType.getTypePtr()))
return false;
const FunctionProtoType *OldType = cast<FunctionProtoType>(OldQType);
const FunctionProtoType *NewType = cast<FunctionProtoType>(NewQType);
if (OldQType != NewQType &&
(OldType->getNumParams() != NewType->getNumParams() ||
OldType->isVariadic() != NewType->isVariadic() ||
!FunctionParamTypesAreEqual(OldType, NewType)))
return true;
if (!UseMemberUsingDeclRules && NewTemplate &&
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
!Context.hasSameType(Old->getDeclaredReturnType(),
New->getDeclaredReturnType())))
return true;
CXXMethodDecl *OldMethod = dyn_cast<CXXMethodDecl>(Old);
CXXMethodDecl *NewMethod = dyn_cast<CXXMethodDecl>(New);
if (OldMethod && NewMethod &&
!OldMethod->isStatic() && !NewMethod->isStatic()) {
if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) {
if (!UseMemberUsingDeclRules &&
(OldMethod->getRefQualifier() == RQ_None ||
NewMethod->getRefQualifier() == RQ_None)) {
Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
<< NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
Diag(OldMethod->getLocation(), diag::note_previous_declaration);
}
return true;
}
auto OldQuals = OldMethod->getMethodQualifiers();
auto NewQuals = NewMethod->getMethodQualifiers();
if (!getLangOpts().CPlusPlus14 && NewMethod->isConstexpr() &&
!isa<CXXConstructorDecl>(NewMethod))
NewQuals.addConst();
OldQuals.removeRestrict();
NewQuals.removeRestrict();
if (OldQuals != NewQuals)
return true;
}
if (functionHasPassObjectSizeParams(New) !=
functionHasPassObjectSizeParams(Old))
return true;
for (specific_attr_iterator<EnableIfAttr>
NewI = New->specific_attr_begin<EnableIfAttr>(),
NewE = New->specific_attr_end<EnableIfAttr>(),
OldI = Old->specific_attr_begin<EnableIfAttr>(),
OldE = Old->specific_attr_end<EnableIfAttr>();
NewI != NewE || OldI != OldE; ++NewI, ++OldI) {
if (NewI == NewE || OldI == OldE)
return true;
llvm::FoldingSetNodeID NewID, OldID;
NewI->getCond()->Profile(NewID, Context, true);
OldI->getCond()->Profile(OldID, Context, true);
if (NewID != OldID)
return true;
}
if (getLangOpts().CUDA && ConsiderCudaAttrs) {
if (!isa<CXXDestructorDecl>(New)) {
CUDAFunctionTarget NewTarget = IdentifyCUDATarget(New),
OldTarget = IdentifyCUDATarget(Old);
if (NewTarget != CFT_InvalidTarget) {
assert((OldTarget != CFT_InvalidTarget) &&
"Unexpected invalid target.");
if (NewTarget != OldTarget)
return true;
}
}
}
if (ConsiderRequiresClauses) {
Expr *NewRC = New->getTrailingRequiresClause(),
*OldRC = Old->getTrailingRequiresClause();
if ((NewRC != nullptr) != (OldRC != nullptr))
return true;
if (NewRC) {
llvm::FoldingSetNodeID NewID, OldID;
NewRC->Profile(NewID, Context, true);
OldRC->Profile(OldID, Context, true);
if (NewID != OldID)
return true;
}
}
return false;
}
static ImplicitConversionSequence
TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
AllowedExplicit AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion,
bool AllowObjCConversionOnExplicit) {
ImplicitConversionSequence ICS;
if (SuppressUserConversions) {
ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
return ICS;
}
OverloadCandidateSet Conversions(From->getExprLoc(),
OverloadCandidateSet::CSK_Normal);
switch (IsUserDefinedConversion(S, From, ToType, ICS.UserDefined,
Conversions, AllowExplicit,
AllowObjCConversionOnExplicit)) {
case OR_Success:
case OR_Deleted:
ICS.setUserDefined();
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) {
QualType FromCanon
= S.Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon
= S.Context.getCanonicalType(ToType).getUnqualifiedType();
if (Constructor->isCopyConstructor() &&
(FromCanon == ToCanon ||
S.IsDerivedFrom(From->getBeginLoc(), FromCanon, ToCanon))) {
DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
ICS.Standard.FoundCopyConstructor = Found;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
}
}
break;
case OR_Ambiguous:
ICS.setAmbiguous();
ICS.Ambiguous.setFromType(From->getType());
ICS.Ambiguous.setToType(ToType);
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
if (Cand->Best)
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
break;
case OR_No_Viable_Function:
ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
break;
}
return ICS;
}
static ImplicitConversionSequence
TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
AllowedExplicit AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion,
bool AllowObjCConversionOnExplicit) {
ImplicitConversionSequence ICS;
if (IsStandardConversion(S, From, ToType, InOverloadResolution,
ICS.Standard, CStyle, AllowObjCWritebackConversion)){
ICS.setStandard();
return ICS;
}
if (!S.getLangOpts().CPlusPlus) {
ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
return ICS;
}
QualType FromType = From->getType();
if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() &&
(S.Context.hasSameUnqualifiedType(FromType, ToType) ||
S.IsDerivedFrom(From->getBeginLoc(), FromType, ToType))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = nullptr;
if (!S.Context.hasSameUnqualifiedType(FromType, ToType))
ICS.Standard.Second = ICK_Derived_To_Base;
return ICS;
}
return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
AllowExplicit, InOverloadResolution, CStyle,
AllowObjCWritebackConversion,
AllowObjCConversionOnExplicit);
}
ImplicitConversionSequence
Sema::TryImplicitConversion(Expr *From, QualType ToType,
bool SuppressUserConversions,
AllowedExplicit AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion) {
return ::TryImplicitConversion(*this, From, ToType, SuppressUserConversions,
AllowExplicit, InOverloadResolution, CStyle,
AllowObjCWritebackConversion,
false);
}
ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action,
bool AllowExplicit) {
if (checkPlaceholderForOverload(*this, From))
return ExprError();
bool AllowObjCWritebackConversion
= getLangOpts().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
if (getLangOpts().ObjC)
CheckObjCBridgeRelatedConversions(From->getBeginLoc(), ToType,
From->getType(), From);
ImplicitConversionSequence ICS = ::TryImplicitConversion(
*this, From, ToType,
false,
AllowExplicit ? AllowedExplicit::All : AllowedExplicit::None,
false,
false, AllowObjCWritebackConversion,
false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
bool Sema::IsFunctionConversion(QualType FromType, QualType ToType,
QualType &ResultTy) {
if (Context.hasSameUnqualifiedType(FromType, ToType))
return false;
CanQualType CanTo = Context.getCanonicalType(ToType);
CanQualType CanFrom = Context.getCanonicalType(FromType);
Type::TypeClass TyClass = CanTo->getTypeClass();
if (TyClass != CanFrom->getTypeClass()) return false;
if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) {
if (TyClass == Type::Pointer) {
CanTo = CanTo.castAs<PointerType>()->getPointeeType();
CanFrom = CanFrom.castAs<PointerType>()->getPointeeType();
} else if (TyClass == Type::BlockPointer) {
CanTo = CanTo.castAs<BlockPointerType>()->getPointeeType();
CanFrom = CanFrom.castAs<BlockPointerType>()->getPointeeType();
} else if (TyClass == Type::MemberPointer) {
auto ToMPT = CanTo.castAs<MemberPointerType>();
auto FromMPT = CanFrom.castAs<MemberPointerType>();
if (ToMPT->getClass() != FromMPT->getClass())
return false;
CanTo = ToMPT->getPointeeType();
CanFrom = FromMPT->getPointeeType();
} else {
return false;
}
TyClass = CanTo->getTypeClass();
if (TyClass != CanFrom->getTypeClass()) return false;
if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto)
return false;
}
const auto *FromFn = cast<FunctionType>(CanFrom);
FunctionType::ExtInfo FromEInfo = FromFn->getExtInfo();
const auto *ToFn = cast<FunctionType>(CanTo);
FunctionType::ExtInfo ToEInfo = ToFn->getExtInfo();
bool Changed = false;
if (FromEInfo.getNoReturn() && !ToEInfo.getNoReturn()) {
FromFn = Context.adjustFunctionType(FromFn, FromEInfo.withNoReturn(false));
Changed = true;
}
if (const auto *FromFPT = dyn_cast<FunctionProtoType>(FromFn)) {
const auto *ToFPT = cast<FunctionProtoType>(ToFn);
if (FromFPT->isNothrow() && !ToFPT->isNothrow()) {
FromFn = cast<FunctionType>(
Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0),
EST_None)
.getTypePtr());
Changed = true;
}
SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos;
bool CanUseToFPT, CanUseFromFPT;
if (Context.mergeExtParameterInfo(ToFPT, FromFPT, CanUseToFPT,
CanUseFromFPT, NewParamInfos) &&
CanUseToFPT && !CanUseFromFPT) {
FunctionProtoType::ExtProtoInfo ExtInfo = FromFPT->getExtProtoInfo();
ExtInfo.ExtParameterInfos =
NewParamInfos.empty() ? nullptr : NewParamInfos.data();
QualType QT = Context.getFunctionType(FromFPT->getReturnType(),
FromFPT->getParamTypes(), ExtInfo);
FromFn = QT->getAs<FunctionType>();
Changed = true;
}
}
if (!Changed)
return false;
assert(QualType(FromFn, 0).isCanonical());
if (QualType(FromFn, 0) != CanTo) return false;
ResultTy = ToType;
return true;
}
static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType,
ImplicitConversionKind &ICK, Expr *From,
bool InOverloadResolution) {
if (!ToType->isVectorType() && !FromType->isVectorType())
return false;
if (S.Context.hasSameUnqualifiedType(FromType, ToType))
return false;
if (ToType->isExtVectorType()) {
if (FromType->isExtVectorType())
return false;
if (FromType->isArithmeticType()) {
ICK = ICK_Vector_Splat;
return true;
}
}
if (ToType->isSizelessBuiltinType() || FromType->isSizelessBuiltinType())
if (S.Context.areCompatibleSveTypes(FromType, ToType) ||
S.Context.areLaxCompatibleSveTypes(FromType, ToType)) {
ICK = ICK_SVE_Vector_Conversion;
return true;
}
if (ToType->isVectorType() && FromType->isVectorType()) {
if (S.Context.areCompatibleVectorTypes(FromType, ToType) ||
(S.isLaxVectorConversion(FromType, ToType) &&
!ToType->hasAttr(attr::ArmMveStrictPolymorphism))) {
if (S.isLaxVectorConversion(FromType, ToType) &&
S.anyAltivecTypes(FromType, ToType) &&
!S.areSameVectorElemTypes(FromType, ToType) &&
!InOverloadResolution) {
S.Diag(From->getBeginLoc(), diag::warn_deprecated_lax_vec_conv_all)
<< FromType << ToType;
}
ICK = ICK_Vector_Conversion;
return true;
}
}
return false;
}
static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle);
static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle,
bool AllowObjCWritebackConversion) {
QualType FromType = From->getType();
SCS.setAsIdentityConversion();
SCS.IncompatibleObjC = false;
SCS.setFromType(FromType);
SCS.CopyConstructor = nullptr;
if (S.getLangOpts().CPlusPlus &&
(FromType->isRecordType() || ToType->isRecordType()))
return false;
if (FromType == S.Context.OverloadTy) {
DeclAccessPair AccessPair;
if (FunctionDecl *Fn
= S.ResolveAddressOfOverloadedFunction(From, ToType, false,
AccessPair)) {
FromType = Fn->getType();
SCS.setFromType(FromType);
if (!S.Context.hasSameUnqualifiedType(
S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
QualType resultTy;
if (!S.IsFunctionConversion(FromType,
S.ExtractUnqualifiedFunctionType(ToType), resultTy))
if (!ToType->isBooleanType())
return false;
}
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn);
if (Method && !Method->isStatic()) {
assert(isa<UnaryOperator>(From->IgnoreParens()) &&
"Non-unary operator on non-static member address");
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode()
== UO_AddrOf &&
"Non-address-of operator on non-static member address");
const Type *ClassType
= S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
FromType = S.Context.getMemberPointerType(FromType, ClassType);
} else if (isa<UnaryOperator>(From->IgnoreParens())) {
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
UO_AddrOf &&
"Non-address-of operator for overloaded function expression");
FromType = S.Context.getPointerType(FromType);
}
} else {
return false;
}
}
bool argIsLValue = From->isGLValue();
if (argIsLValue &&
!FromType->isFunctionType() && !FromType->isArrayType() &&
S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) {
SCS.First = ICK_Lvalue_To_Rvalue;
if (const AtomicType *Atomic = FromType->getAs<AtomicType>())
FromType = Atomic->getValueType();
FromType = FromType.getUnqualifiedType();
} else if (FromType->isArrayType()) {
SCS.First = ICK_Array_To_Pointer;
FromType = S.Context.getArrayDecayedType(FromType);
if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
SCS.DeprecatedStringLiteralToCharPtr = true;
SCS.Second = ICK_Identity;
SCS.Third = ICK_Qualification;
SCS.QualificationIncludesObjCLifetime = false;
SCS.setAllToTypes(FromType);
return true;
}
} else if (FromType->isFunctionType() && argIsLValue) {
SCS.First = ICK_Function_To_Pointer;
if (auto *DRE = dyn_cast<DeclRefExpr>(From->IgnoreParenCasts()))
if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
if (!S.checkAddressOfFunctionIsAvailable(FD))
return false;
FromType = S.Context.getPointerType(FromType);
} else {
SCS.First = ICK_Identity;
}
SCS.setToType(0, FromType);
bool IncompatibleObjC = false;
ImplicitConversionKind SecondICK = ICK_Identity;
if (S.Context.hasSameUnqualifiedType(FromType, ToType)) {
SCS.Second = ICK_Identity;
} else if (S.IsIntegralPromotion(From, FromType, ToType)) {
SCS.Second = ICK_Integral_Promotion;
FromType = ToType.getUnqualifiedType();
} else if (S.IsFloatingPointPromotion(FromType, ToType)) {
SCS.Second = ICK_Floating_Promotion;
FromType = ToType.getUnqualifiedType();
} else if (S.IsComplexPromotion(FromType, ToType)) {
SCS.Second = ICK_Complex_Promotion;
FromType = ToType.getUnqualifiedType();
} else if (ToType->isBooleanType() &&
(FromType->isArithmeticType() ||
FromType->isAnyPointerType() ||
FromType->isBlockPointerType() ||
FromType->isMemberPointerType())) {
SCS.Second = ICK_Boolean_Conversion;
FromType = S.Context.BoolTy;
} else if (FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isIntegralType(S.Context)) {
SCS.Second = ICK_Integral_Conversion;
FromType = ToType.getUnqualifiedType();
} else if (FromType->isAnyComplexType() && ToType->isAnyComplexType()) {
SCS.Second = ICK_Complex_Conversion;
FromType = ToType.getUnqualifiedType();
} else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) ||
(ToType->isAnyComplexType() && FromType->isArithmeticType())) {
SCS.Second = ICK_Complex_Real;
FromType = ToType.getUnqualifiedType();
} else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) {
if (FromType == S.Context.BFloat16Ty || ToType == S.Context.BFloat16Ty)
return false;
const llvm::fltSemantics &FromSem =
S.Context.getFloatTypeSemantics(FromType);
const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType);
if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() &&
&ToSem == &llvm::APFloat::IEEEquad()) ||
(&FromSem == &llvm::APFloat::IEEEquad() &&
&ToSem == &llvm::APFloat::PPCDoubleDouble()))
return false;
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
} else if ((FromType->isRealFloatingType() &&
ToType->isIntegralType(S.Context)) ||
(FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isRealFloatingType())) {
if (FromType->isBFloat16Type() || ToType->isBFloat16Type())
return false;
SCS.Second = ICK_Floating_Integral;
FromType = ToType.getUnqualifiedType();
} else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) {
SCS.Second = ICK_Block_Pointer_Conversion;
} else if (AllowObjCWritebackConversion &&
S.isObjCWritebackConversion(FromType, ToType, FromType)) {
SCS.Second = ICK_Writeback_Conversion;
} else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution,
FromType, IncompatibleObjC)) {
SCS.Second = ICK_Pointer_Conversion;
SCS.IncompatibleObjC = IncompatibleObjC;
FromType = FromType.getUnqualifiedType();
} else if (S.IsMemberPointerConversion(From, FromType, ToType,
InOverloadResolution, FromType)) {
SCS.Second = ICK_Pointer_Member;
} else if (IsVectorConversion(S, FromType, ToType, SecondICK, From,
InOverloadResolution)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
} else if (!S.getLangOpts().CPlusPlus &&
S.Context.typesAreCompatible(ToType, FromType)) {
SCS.Second = ICK_Compatible_Conversion;
FromType = ToType.getUnqualifiedType();
} else if (IsTransparentUnionStandardConversion(S, From, ToType,
InOverloadResolution,
SCS, CStyle)) {
SCS.Second = ICK_TransparentUnionConversion;
FromType = ToType;
} else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS,
CStyle)) {
return true;
} else if (ToType->isEventT() &&
From->isIntegerConstantExpr(S.getASTContext()) &&
From->EvaluateKnownConstInt(S.getASTContext()) == 0) {
SCS.Second = ICK_Zero_Event_Conversion;
FromType = ToType;
} else if (ToType->isQueueT() &&
From->isIntegerConstantExpr(S.getASTContext()) &&
(From->EvaluateKnownConstInt(S.getASTContext()) == 0)) {
SCS.Second = ICK_Zero_Queue_Conversion;
FromType = ToType;
} else if (ToType->isSamplerT() &&
From->isIntegerConstantExpr(S.getASTContext())) {
SCS.Second = ICK_Compatible_Conversion;
FromType = ToType;
} else {
SCS.Second = ICK_Identity;
}
SCS.setToType(1, FromType);
bool ObjCLifetimeConversion;
if (S.IsFunctionConversion(FromType, ToType, FromType)) {
SCS.Third = ICK_Function_Conversion;
} else if (S.IsQualificationConversion(FromType, ToType, CStyle,
ObjCLifetimeConversion)) {
SCS.Third = ICK_Qualification;
SCS.QualificationIncludesObjCLifetime = ObjCLifetimeConversion;
FromType = ToType;
} else {
SCS.Third = ICK_Identity;
}
QualType CanonFrom = S.Context.getCanonicalType(FromType);
QualType CanonTo = S.Context.getCanonicalType(ToType);
if (CanonFrom.getLocalUnqualifiedType()
== CanonTo.getLocalUnqualifiedType() &&
CanonFrom.getLocalQualifiers() != CanonTo.getLocalQualifiers()) {
FromType = ToType;
CanonFrom = CanonTo;
}
SCS.setToType(2, FromType);
if (CanonFrom == CanonTo)
return true;
if (S.getLangOpts().CPlusPlus || !InOverloadResolution)
return false;
ExprResult ER = ExprResult{From};
Sema::AssignConvertType Conv =
S.CheckSingleAssignmentConstraints(ToType, ER,
false,
false,
false);
ImplicitConversionKind SecondConv;
switch (Conv) {
case Sema::Compatible:
SecondConv = ICK_C_Only_Conversion;
break;
case Sema::CompatiblePointerDiscardsQualifiers:
case Sema::IncompatiblePointer:
case Sema::IncompatiblePointerSign:
SecondConv = ICK_Incompatible_Pointer_Conversion;
break;
default:
return false;
}
SCS.Second = SecondConv;
SCS.setToType(1, ToType);
SCS.Third = ICK_Identity;
SCS.setToType(2, ToType);
return true;
}
static bool
IsTransparentUnionStandardConversion(Sema &S, Expr* From,
QualType &ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle) {
const RecordType *UT = ToType->getAsUnionType();
if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
return false;
RecordDecl *UD = UT->getDecl();
for (const auto *it : UD->fields()) {
if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS,
CStyle, false)) {
ToType = it->getType();
return true;
}
}
return false;
}
bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) {
const BuiltinType *To = ToType->getAs<BuiltinType>();
if (!To) {
return false;
}
if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() &&
!FromType->isEnumeralType()) {
if ( (FromType->isSignedIntegerType() ||
Context.getTypeSize(FromType) < Context.getTypeSize(ToType))) {
return To->getKind() == BuiltinType::Int;
}
return To->getKind() == BuiltinType::UInt;
}
if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) {
if (FromEnumType->getDecl()->isScoped())
return false;
if (FromEnumType->getDecl()->isFixed()) {
QualType Underlying = FromEnumType->getDecl()->getIntegerType();
return Context.hasSameUnqualifiedType(Underlying, ToType) ||
IsIntegralPromotion(nullptr, Underlying, ToType);
}
if (ToType->isIntegerType() &&
isCompleteType(From->getBeginLoc(), FromType))
return Context.hasSameUnqualifiedType(
ToType, FromEnumType->getDecl()->getPromotionType());
if (getLangOpts().CPlusPlus)
return false;
}
if (FromType->isAnyCharacterType() && !FromType->isCharType() &&
ToType->isIntegerType()) {
bool FromIsSigned = FromType->isSignedIntegerType();
uint64_t FromSize = Context.getTypeSize(FromType);
QualType PromoteTypes[6] = {
Context.IntTy, Context.UnsignedIntTy,
Context.LongTy, Context.UnsignedLongTy ,
Context.LongLongTy, Context.UnsignedLongLongTy
};
for (int Idx = 0; Idx < 6; ++Idx) {
uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]);
if (FromSize < ToSize ||
(FromSize == ToSize &&
FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) {
return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]);
}
}
}
if (From) {
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
Optional<llvm::APSInt> BitWidth;
if (FromType->isIntegralType(Context) &&
(BitWidth =
MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) {
llvm::APSInt ToSize(BitWidth->getBitWidth(), BitWidth->isUnsigned());
ToSize = Context.getTypeSize(ToType);
if (*BitWidth < ToSize ||
(FromType->isSignedIntegerType() && *BitWidth <= ToSize)) {
return To->getKind() == BuiltinType::Int;
}
if (FromType->isUnsignedIntegerType() && *BitWidth <= ToSize) {
return To->getKind() == BuiltinType::UInt;
}
return false;
}
}
}
if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) {
return true;
}
return false;
}
bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) {
if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>())
if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) {
if (FromBuiltin->getKind() == BuiltinType::Float &&
ToBuiltin->getKind() == BuiltinType::Double)
return true;
if (!getLangOpts().CPlusPlus &&
(FromBuiltin->getKind() == BuiltinType::Float ||
FromBuiltin->getKind() == BuiltinType::Double) &&
(ToBuiltin->getKind() == BuiltinType::LongDouble ||
ToBuiltin->getKind() == BuiltinType::Float128 ||
ToBuiltin->getKind() == BuiltinType::Ibm128))
return true;
if (!getLangOpts().NativeHalfType &&
FromBuiltin->getKind() == BuiltinType::Half &&
ToBuiltin->getKind() == BuiltinType::Float)
return true;
}
return false;
}
bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) {
const ComplexType *FromComplex = FromType->getAs<ComplexType>();
if (!FromComplex)
return false;
const ComplexType *ToComplex = ToType->getAs<ComplexType>();
if (!ToComplex)
return false;
return IsFloatingPointPromotion(FromComplex->getElementType(),
ToComplex->getElementType()) ||
IsIntegralPromotion(nullptr, FromComplex->getElementType(),
ToComplex->getElementType());
}
static QualType
BuildSimilarlyQualifiedPointerType(const Type *FromPtr,
QualType ToPointee, QualType ToType,
ASTContext &Context,
bool StripObjCLifetime = false) {
assert((FromPtr->getTypeClass() == Type::Pointer ||
FromPtr->getTypeClass() == Type::ObjCObjectPointer) &&
"Invalid similarly-qualified pointer type");
if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType())
return ToType.getUnqualifiedType();
QualType CanonFromPointee
= Context.getCanonicalType(FromPtr->getPointeeType());
QualType CanonToPointee = Context.getCanonicalType(ToPointee);
Qualifiers Quals = CanonFromPointee.getQualifiers();
if (StripObjCLifetime)
Quals.removeObjCLifetime();
if (CanonToPointee.getLocalQualifiers() == Quals) {
if (!ToType.isNull())
return ToType.getUnqualifiedType();
if (isa<ObjCObjectPointerType>(ToType))
return Context.getObjCObjectPointerType(ToPointee);
return Context.getPointerType(ToPointee);
}
QualType QualifiedCanonToPointee
= Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals);
if (isa<ObjCObjectPointerType>(ToType))
return Context.getObjCObjectPointerType(QualifiedCanonToPointee);
return Context.getPointerType(QualifiedCanonToPointee);
}
static bool isNullPointerConstantForConversion(Expr *Expr,
bool InOverloadResolution,
ASTContext &Context) {
if (Expr->isValueDependent() && !Expr->isTypeDependent() &&
Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType())
return !InOverloadResolution;
return Expr->isNullPointerConstant(Context,
InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
: Expr::NPC_ValueDependentIsNull);
}
bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
bool InOverloadResolution,
QualType& ConvertedType,
bool &IncompatibleObjC) {
IncompatibleObjC = false;
if (isObjCPointerConversion(FromType, ToType, ConvertedType,
IncompatibleObjC))
return true;
if (ToType->isObjCObjectPointerType() &&
isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
ConvertedType = ToType;
return true;
}
if (FromType->isBlockPointerType() && ToType->isPointerType() &&
ToType->castAs<PointerType>()->getPointeeType()->isVoidType()) {
ConvertedType = ToType;
return true;
}
if (ToType->isBlockPointerType() &&
isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
ConvertedType = ToType;
return true;
}
if (ToType->isNullPtrType() &&
isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
ConvertedType = ToType;
return true;
}
const PointerType* ToTypePtr = ToType->getAs<PointerType>();
if (!ToTypePtr)
return false;
if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) {
ConvertedType = ToType;
return true;
}
QualType ToPointeeType = ToTypePtr->getPointeeType();
if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType() &&
!getLangOpts().ObjCAutoRefCount) {
ConvertedType = BuildSimilarlyQualifiedPointerType(
FromType->castAs<ObjCObjectPointerType>(), ToPointeeType, ToType,
Context);
return true;
}
const PointerType *FromTypePtr = FromType->getAs<PointerType>();
if (!FromTypePtr)
return false;
QualType FromPointeeType = FromTypePtr->getPointeeType();
if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType))
return false;
if (FromPointeeType->isIncompleteOrObjectType() &&
ToPointeeType->isVoidType()) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context,
true);
return true;
}
if (getLangOpts().MSVCCompat && FromPointeeType->isFunctionType() &&
ToPointeeType->isVoidType()) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
return true;
}
if (!getLangOpts().CPlusPlus &&
Context.typesAreCompatible(FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
return true;
}
if (getLangOpts().CPlusPlus && FromPointeeType->isRecordType() &&
ToPointeeType->isRecordType() &&
!Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) &&
IsDerivedFrom(From->getBeginLoc(), FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
return true;
}
if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() &&
Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) {
ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
ToPointeeType,
ToType, Context);
return true;
}
return false;
}
static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){
Qualifiers TQs = T.getQualifiers();
if (TQs == Qs)
return T;
if (Qs.compatiblyIncludes(TQs))
return Context.getQualifiedType(T, Qs);
return Context.getQualifiedType(T.getUnqualifiedType(), Qs);
}
bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType,
bool &IncompatibleObjC) {
if (!getLangOpts().ObjC)
return false;
Qualifiers FromQualifiers = FromType.getQualifiers();
const ObjCObjectPointerType* ToObjCPtr =
ToType->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *FromObjCPtr =
FromType->getAs<ObjCObjectPointerType>();
if (ToObjCPtr && FromObjCPtr) {
if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(),
FromObjCPtr->getPointeeType()))
return false;
if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) {
const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType();
const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType();
if (getLangOpts().CPlusPlus && LHS && RHS &&
!ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs(
FromObjCPtr->getPointeeType()))
return false;
ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
ToObjCPtr->getPointeeType(),
ToType, Context);
ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) {
IncompatibleObjC = true;
ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr,
ToObjCPtr->getPointeeType(),
ToType, Context);
ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
}
QualType ToPointeeType;
if (const PointerType *ToCPtr = ToType->getAs<PointerType>())
ToPointeeType = ToCPtr->getPointeeType();
else if (const BlockPointerType *ToBlockPtr =
ToType->getAs<BlockPointerType>()) {
if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) {
ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
ToPointeeType = ToBlockPtr->getPointeeType();
}
else if (FromType->getAs<BlockPointerType>() &&
ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) {
ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
else
return false;
QualType FromPointeeType;
if (const PointerType *FromCPtr = FromType->getAs<PointerType>())
FromPointeeType = FromCPtr->getPointeeType();
else if (const BlockPointerType *FromBlockPtr =
FromType->getAs<BlockPointerType>())
FromPointeeType = FromBlockPtr->getPointeeType();
else
return false;
if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() &&
isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
IncompatibleObjC)) {
IncompatibleObjC = true;
ConvertedType = Context.getPointerType(ConvertedType);
ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
if (FromPointeeType->getAs<ObjCObjectPointerType>() &&
ToPointeeType->getAs<ObjCObjectPointerType>() &&
isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
IncompatibleObjC)) {
ConvertedType = Context.getPointerType(ConvertedType);
ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers);
return true;
}
const FunctionProtoType *FromFunctionType
= FromPointeeType->getAs<FunctionProtoType>();
const FunctionProtoType *ToFunctionType
= ToPointeeType->getAs<FunctionProtoType>();
if (FromFunctionType && ToFunctionType) {
if (Context.getCanonicalType(FromPointeeType)
== Context.getCanonicalType(ToPointeeType))
return false;
if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() ||
FromFunctionType->isVariadic() != ToFunctionType->isVariadic() ||
FromFunctionType->getMethodQuals() != ToFunctionType->getMethodQuals())
return false;
bool HasObjCConversion = false;
if (Context.getCanonicalType(FromFunctionType->getReturnType()) ==
Context.getCanonicalType(ToFunctionType->getReturnType())) {
} else if (isObjCPointerConversion(FromFunctionType->getReturnType(),
ToFunctionType->getReturnType(),
ConvertedType, IncompatibleObjC)) {
HasObjCConversion = true;
} else {
return false;
}
for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams();
ArgIdx != NumArgs; ++ArgIdx) {
QualType FromArgType = FromFunctionType->getParamType(ArgIdx);
QualType ToArgType = ToFunctionType->getParamType(ArgIdx);
if (Context.getCanonicalType(FromArgType)
== Context.getCanonicalType(ToArgType)) {
} else if (isObjCPointerConversion(FromArgType, ToArgType,
ConvertedType, IncompatibleObjC)) {
HasObjCConversion = true;
} else {
return false;
}
}
if (HasObjCConversion) {
ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
IncompatibleObjC = true;
return true;
}
}
return false;
}
bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType,
QualType &ConvertedType) {
if (!getLangOpts().ObjCAutoRefCount ||
Context.hasSameUnqualifiedType(FromType, ToType))
return false;
QualType ToPointee;
if (const PointerType *ToPointer = ToType->getAs<PointerType>())
ToPointee = ToPointer->getPointeeType();
else
return false;
Qualifiers ToQuals = ToPointee.getQualifiers();
if (!ToPointee->isObjCLifetimeType() ||
ToQuals.getObjCLifetime() != Qualifiers::OCL_Autoreleasing ||
!ToQuals.withoutObjCLifetime().empty())
return false;
QualType FromPointee;
if (const PointerType *FromPointer = FromType->getAs<PointerType>())
FromPointee = FromPointer->getPointeeType();
else
return false;
Qualifiers FromQuals = FromPointee.getQualifiers();
if (!FromPointee->isObjCLifetimeType() ||
(FromQuals.getObjCLifetime() != Qualifiers::OCL_Strong &&
FromQuals.getObjCLifetime() != Qualifiers::OCL_Weak))
return false;
FromQuals.setObjCLifetime(Qualifiers::OCL_Autoreleasing);
if (!ToQuals.compatiblyIncludes(FromQuals))
return false;
FromPointee = FromPointee.getUnqualifiedType();
ToPointee = ToPointee.getUnqualifiedType();
bool IncompatibleObjC;
if (Context.typesAreCompatible(FromPointee, ToPointee))
FromPointee = ToPointee;
else if (!isObjCPointerConversion(FromPointee, ToPointee, FromPointee,
IncompatibleObjC))
return false;
FromPointee = Context.getQualifiedType(FromPointee, FromQuals);
ConvertedType = Context.getPointerType(FromPointee);
return true;
}
bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
QualType& ConvertedType) {
QualType ToPointeeType;
if (const BlockPointerType *ToBlockPtr =
ToType->getAs<BlockPointerType>())
ToPointeeType = ToBlockPtr->getPointeeType();
else
return false;
QualType FromPointeeType;
if (const BlockPointerType *FromBlockPtr =
FromType->getAs<BlockPointerType>())
FromPointeeType = FromBlockPtr->getPointeeType();
else
return false;
const FunctionProtoType *FromFunctionType
= FromPointeeType->getAs<FunctionProtoType>();
const FunctionProtoType *ToFunctionType
= ToPointeeType->getAs<FunctionProtoType>();
if (!FromFunctionType || !ToFunctionType)
return false;
if (Context.hasSameType(FromPointeeType, ToPointeeType))
return true;
if (FromFunctionType->getNumParams() != ToFunctionType->getNumParams() ||
FromFunctionType->isVariadic() != ToFunctionType->isVariadic())
return false;
FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo();
FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo();
if (FromEInfo != ToEInfo)
return false;
bool IncompatibleObjC = false;
if (Context.hasSameType(FromFunctionType->getReturnType(),
ToFunctionType->getReturnType())) {
} else {
QualType RHS = FromFunctionType->getReturnType();
QualType LHS = ToFunctionType->getReturnType();
if ((!getLangOpts().CPlusPlus || !RHS->isRecordType()) &&
!RHS.hasQualifiers() && LHS.hasQualifiers())
LHS = LHS.getUnqualifiedType();
if (Context.hasSameType(RHS,LHS)) {
} else if (isObjCPointerConversion(RHS, LHS,
ConvertedType, IncompatibleObjC)) {
if (IncompatibleObjC)
return false;
}
else
return false;
}
for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumParams();
ArgIdx != NumArgs; ++ArgIdx) {
IncompatibleObjC = false;
QualType FromArgType = FromFunctionType->getParamType(ArgIdx);
QualType ToArgType = ToFunctionType->getParamType(ArgIdx);
if (Context.hasSameType(FromArgType, ToArgType)) {
} else if (isObjCPointerConversion(ToArgType, FromArgType,
ConvertedType, IncompatibleObjC)) {
if (IncompatibleObjC)
return false;
} else
return false;
}
SmallVector<FunctionProtoType::ExtParameterInfo, 4> NewParamInfos;
bool CanUseToFPT, CanUseFromFPT;
if (!Context.mergeExtParameterInfo(ToFunctionType, FromFunctionType,
CanUseToFPT, CanUseFromFPT,
NewParamInfos))
return false;
ConvertedType = ToType;
return true;
}
enum {
ft_default,
ft_different_class,
ft_parameter_arity,
ft_parameter_mismatch,
ft_return_type,
ft_qualifer_mismatch,
ft_noexcept
};
static const FunctionProtoType *tryGetFunctionProtoType(QualType FromType) {
if (auto *FPT = FromType->getAs<FunctionProtoType>())
return FPT;
if (auto *MPT = FromType->getAs<MemberPointerType>())
return MPT->getPointeeType()->getAs<FunctionProtoType>();
return nullptr;
}
void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
QualType FromType, QualType ToType) {
if (FromType.isNull() || ToType.isNull()) {
PDiag << ft_default;
return;
}
if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) {
const auto *FromMember = FromType->castAs<MemberPointerType>(),
*ToMember = ToType->castAs<MemberPointerType>();
if (!Context.hasSameType(FromMember->getClass(), ToMember->getClass())) {
PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
<< QualType(FromMember->getClass(), 0);
return;
}
FromType = FromMember->getPointeeType();
ToType = ToMember->getPointeeType();
}
if (FromType->isPointerType())
FromType = FromType->getPointeeType();
if (ToType->isPointerType())
ToType = ToType->getPointeeType();
FromType = FromType.getNonReferenceType();
ToType = ToType.getNonReferenceType();
if (FromType->isInstantiationDependentType() &&
!FromType->getAs<TemplateSpecializationType>()) {
PDiag << ft_default;
return;
}
if (Context.hasSameType(FromType, ToType)) {
PDiag << ft_default;
return;
}
const FunctionProtoType *FromFunction = tryGetFunctionProtoType(FromType),
*ToFunction = tryGetFunctionProtoType(ToType);
if (!FromFunction || !ToFunction) {
PDiag << ft_default;
return;
}
if (FromFunction->getNumParams() != ToFunction->getNumParams()) {
PDiag << ft_parameter_arity << ToFunction->getNumParams()
<< FromFunction->getNumParams();
return;
}
unsigned ArgPos;
if (!FunctionParamTypesAreEqual(FromFunction, ToFunction, &ArgPos)) {
PDiag << ft_parameter_mismatch << ArgPos + 1
<< ToFunction->getParamType(ArgPos)
<< FromFunction->getParamType(ArgPos);
return;
}
if (!Context.hasSameType(FromFunction->getReturnType(),
ToFunction->getReturnType())) {
PDiag << ft_return_type << ToFunction->getReturnType()
<< FromFunction->getReturnType();
return;
}
if (FromFunction->getMethodQuals() != ToFunction->getMethodQuals()) {
PDiag << ft_qualifer_mismatch << ToFunction->getMethodQuals()
<< FromFunction->getMethodQuals();
return;
}
if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified())
->isNothrow() !=
cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified())
->isNothrow()) {
PDiag << ft_noexcept;
return;
}
PDiag << ft_default;
}
bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
const FunctionProtoType *NewType,
unsigned *ArgPos, bool Reversed) {
assert(OldType->getNumParams() == NewType->getNumParams() &&
"Can't compare parameters of functions with different number of "
"parameters!");
for (size_t I = 0; I < OldType->getNumParams(); I++) {
size_t J = Reversed ? (OldType->getNumParams() - I - 1) : I;
QualType Old = Context.removePtrSizeAddrSpace(OldType->getParamType(I).getUnqualifiedType());
QualType New = Context.removePtrSizeAddrSpace(NewType->getParamType(J).getUnqualifiedType());
if (!Context.hasSameType(Old, New)) {
if (ArgPos)
*ArgPos = I;
return false;
}
}
return true;
}
bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
CastKind &Kind,
CXXCastPath& BasePath,
bool IgnoreBaseAccess,
bool Diagnose) {
QualType FromType = From->getType();
bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
Kind = CK_BitCast;
if (Diagnose && !IsCStyleOrFunctionalCast && !FromType->isAnyPointerType() &&
From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) ==
Expr::NPCK_ZeroExpression) {
if (Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy))
DiagRuntimeBehavior(From->getExprLoc(), From,
PDiag(diag::warn_impcast_bool_to_null_pointer)
<< ToType << From->getSourceRange());
else if (!isUnevaluatedContext())
Diag(From->getExprLoc(), diag::warn_non_literal_null_pointer)
<< ToType << From->getSourceRange();
}
if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) {
QualType FromPointeeType = FromPtrType->getPointeeType(),
ToPointeeType = ToPtrType->getPointeeType();
if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() &&
!Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) {
unsigned InaccessibleID = 0;
unsigned AmbiguousID = 0;
if (Diagnose) {
InaccessibleID = diag::err_upcast_to_inaccessible_base;
AmbiguousID = diag::err_ambiguous_derived_to_base_conv;
}
if (CheckDerivedToBaseConversion(
FromPointeeType, ToPointeeType, InaccessibleID, AmbiguousID,
From->getExprLoc(), From->getSourceRange(), DeclarationName(),
&BasePath, IgnoreBaseAccess))
return true;
Kind = CK_DerivedToBase;
}
if (Diagnose && !IsCStyleOrFunctionalCast &&
FromPointeeType->isFunctionType() && ToPointeeType->isVoidType()) {
assert(getLangOpts().MSVCCompat &&
"this should only be possible with MSVCCompat!");
Diag(From->getExprLoc(), diag::ext_ms_impcast_fn_obj)
<< From->getSourceRange();
}
}
} else if (const ObjCObjectPointerType *ToPtrType =
ToType->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *FromPtrType =
FromType->getAs<ObjCObjectPointerType>()) {
if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
return false;
} else if (FromType->isBlockPointerType()) {
Kind = CK_BlockPointerToObjCPointerCast;
} else {
Kind = CK_CPointerToObjCPointerCast;
}
} else if (ToType->isBlockPointerType()) {
if (!FromType->isBlockPointerType())
Kind = CK_AnyPointerToBlockPointerCast;
}
if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
Kind = CK_NullToPointer;
return false;
}
bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
QualType ToType,
bool InOverloadResolution,
QualType &ConvertedType) {
const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>();
if (!ToTypePtr)
return false;
if (From->isNullPointerConstant(Context,
InOverloadResolution? Expr::NPC_ValueDependentIsNotNull
: Expr::NPC_ValueDependentIsNull)) {
ConvertedType = ToType;
return true;
}
const MemberPointerType *FromTypePtr = FromType->getAs<MemberPointerType>();
if (!FromTypePtr)
return false;
QualType FromClass(FromTypePtr->getClass(), 0);
QualType ToClass(ToTypePtr->getClass(), 0);
if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) {
ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
ToClass.getTypePtr());
return true;
}
return false;
}
bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType,
CastKind &Kind,
CXXCastPath &BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>();
if (!FromPtrType) {
assert(From->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull) &&
"Expr must be null pointer constant!");
Kind = CK_NullToMemberPointer;
return false;
}
const MemberPointerType *ToPtrType = ToType->getAs<MemberPointerType>();
assert(ToPtrType && "No member pointer cast has a target type "
"that is not a member pointer.");
QualType FromClass = QualType(FromPtrType->getClass(), 0);
QualType ToClass = QualType(ToPtrType->getClass(), 0);
assert(FromClass->isRecordType() && "Pointer into non-class.");
assert(ToClass->isRecordType() && "Pointer into non-class.");
CXXBasePaths Paths(true, true,
true);
bool DerivationOkay =
IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass, Paths);
assert(DerivationOkay &&
"Should not have been called if derivation isn't OK.");
(void)DerivationOkay;
if (Paths.isAmbiguous(Context.getCanonicalType(FromClass).
getUnqualifiedType())) {
std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv)
<< 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange();
return true;
}
if (const RecordType *VBase = Paths.getDetectedVirtual()) {
Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual)
<< FromClass << ToClass << QualType(VBase, 0)
<< From->getSourceRange();
return true;
}
if (!IgnoreBaseAccess)
CheckBaseClassAccess(From->getExprLoc(), FromClass, ToClass,
Paths.front(),
diag::err_downcast_from_inaccessible_base);
BuildBasePathArray(Paths, BasePath);
Kind = CK_BaseToDerivedMemberPointer;
return false;
}
static bool isNonTrivialObjCLifetimeConversion(Qualifiers FromQuals,
Qualifiers ToQuals) {
if (ToQuals.hasConst() &&
ToQuals.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
return false;
return true;
}
static bool isQualificationConversionStep(QualType FromType, QualType ToType,
bool CStyle, bool IsTopLevel,
bool &PreviousToQualsIncludeConst,
bool &ObjCLifetimeConversion) {
Qualifiers FromQuals = FromType.getQualifiers();
Qualifiers ToQuals = ToType.getQualifiers();
FromQuals.removeUnaligned();
if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime()) {
if (ToQuals.compatiblyIncludesObjCLifetime(FromQuals)) {
if (isNonTrivialObjCLifetimeConversion(FromQuals, ToQuals))
ObjCLifetimeConversion = true;
FromQuals.removeObjCLifetime();
ToQuals.removeObjCLifetime();
} else {
return false;
}
}
if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() &&
(!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) {
FromQuals.removeObjCGCAttr();
ToQuals.removeObjCGCAttr();
}
if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals))
return false;
if (ToQuals.getAddressSpace() != FromQuals.getAddressSpace() &&
(!IsTopLevel ||
!(ToQuals.isAddressSpaceSupersetOf(FromQuals) ||
(CStyle && FromQuals.isAddressSpaceSupersetOf(ToQuals)))))
return false;
if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers() &&
!PreviousToQualsIncludeConst)
return false;
if (FromType->isIncompleteArrayType() && !ToType->isIncompleteArrayType())
return false;
if (!CStyle && FromType->isConstantArrayType() &&
ToType->isIncompleteArrayType() && !PreviousToQualsIncludeConst)
return false;
PreviousToQualsIncludeConst =
PreviousToQualsIncludeConst && ToQuals.hasConst();
return true;
}
bool
Sema::IsQualificationConversion(QualType FromType, QualType ToType,
bool CStyle, bool &ObjCLifetimeConversion) {
FromType = Context.getCanonicalType(FromType);
ToType = Context.getCanonicalType(ToType);
ObjCLifetimeConversion = false;
if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType())
return false;
bool PreviousToQualsIncludeConst = true;
bool UnwrappedAnyPointer = false;
while (Context.UnwrapSimilarTypes(FromType, ToType)) {
if (!isQualificationConversionStep(
FromType, ToType, CStyle, !UnwrappedAnyPointer,
PreviousToQualsIncludeConst, ObjCLifetimeConversion))
return false;
UnwrappedAnyPointer = true;
}
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
}
static bool tryAtomicConversion(Sema &S, Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence &SCS,
bool CStyle) {
const AtomicType *ToAtomic = ToType->getAs<AtomicType>();
if (!ToAtomic)
return false;
StandardConversionSequence InnerSCS;
if (!IsStandardConversion(S, From, ToAtomic->getValueType(),
InOverloadResolution, InnerSCS,
CStyle, false))
return false;
SCS.Second = InnerSCS.Second;
SCS.setToType(1, InnerSCS.getToType(1));
SCS.Third = InnerSCS.Third;
SCS.QualificationIncludesObjCLifetime
= InnerSCS.QualificationIncludesObjCLifetime;
SCS.setToType(2, InnerSCS.getToType(2));
return true;
}
static bool isFirstArgumentCompatibleWithType(ASTContext &Context,
CXXConstructorDecl *Constructor,
QualType Type) {
const auto *CtorType = Constructor->getType()->castAs<FunctionProtoType>();
if (CtorType->getNumParams() > 0) {
QualType FirstArg = CtorType->getParamType(0);
if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType()))
return true;
}
return false;
}
static OverloadingResult
IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
CXXRecordDecl *To,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
bool AllowExplicit) {
CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
for (auto *D : S.LookupConstructors(To)) {
auto Info = getConstructorInfo(D);
if (!Info)
continue;
bool Usable = !Info.Constructor->isInvalidDecl() &&
S.isInitListConstructor(Info.Constructor);
if (Usable) {
bool SuppressUserConversions = false;
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
nullptr, From,
CandidateSet, SuppressUserConversions,
false,
AllowExplicit);
else
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From,
CandidateSet, SuppressUserConversions,
false, AllowExplicit);
}
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (auto Result =
CandidateSet.BestViableFunction(S, From->getBeginLoc(), Best)) {
case OR_Deleted:
case OR_Success: {
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
QualType ThisType = Constructor->getThisType();
User.Before.setAsIdentityConversion();
User.HadMultipleCandidates = HadMultipleCandidates;
User.ConversionFunction = Constructor;
User.FoundConversionFunction = Best->FoundDecl;
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->castAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
return Result;
}
case OR_No_Viable_Function:
return OR_No_Viable_Function;
case OR_Ambiguous:
return OR_Ambiguous;
}
llvm_unreachable("Invalid OverloadResult!");
}
static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
AllowedExplicit AllowExplicit,
bool AllowObjCConversionOnExplicit) {
assert(AllowExplicit != AllowedExplicit::None ||
!AllowObjCConversionOnExplicit);
CandidateSet.clear(OverloadCandidateSet::CSK_InitByUserDefinedConversion);
bool ConstructorsOnly = false;
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
(From->getType()->getAs<RecordType>() &&
S.IsDerivedFrom(From->getBeginLoc(), From->getType(), ToType)))
ConstructorsOnly = true;
if (!S.isCompleteType(From->getExprLoc(), ToType)) {
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
Expr **Args = &From;
unsigned NumArgs = 1;
bool ListInitializing = false;
if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) {
OverloadingResult Result = IsInitializerListConstructorConversion(
S, From, ToType, ToRecordDecl, User, CandidateSet,
AllowExplicit == AllowedExplicit::All);
if (Result != OR_No_Viable_Function)
return Result;
CandidateSet.clear(
OverloadCandidateSet::CSK_InitByUserDefinedConversion);
Args = InitList->getInits();
NumArgs = InitList->getNumInits();
ListInitializing = true;
}
for (auto *D : S.LookupConstructors(ToRecordDecl)) {
auto Info = getConstructorInfo(D);
if (!Info)
continue;
bool Usable = !Info.Constructor->isInvalidDecl();
if (!ListInitializing)
Usable = Usable && Info.Constructor->isConvertingConstructor(
true);
if (Usable) {
bool SuppressUserConversions = !ConstructorsOnly;
if (SuppressUserConversions && ListInitializing) {
SuppressUserConversions =
NumArgs == 1 && isa<InitListExpr>(Args[0]) &&
isFirstArgumentCompatibleWithType(S.Context, Info.Constructor,
ToType);
}
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(
Info.ConstructorTmpl, Info.FoundDecl,
nullptr, llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions,
false,
AllowExplicit == AllowedExplicit::All);
else
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions,
false,
AllowExplicit == AllowedExplicit::All);
}
}
}
}
if (ConstructorsOnly || isa<InitListExpr>(From)) {
} else if (!S.isCompleteType(From->getBeginLoc(), From->getType())) {
} else if (const RecordType *FromRecordType =
From->getType()->getAs<RecordType>()) {
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
const auto &Conversions = FromRecordDecl->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
DeclAccessPair FoundDecl = I.getPair();
NamedDecl *D = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
CXXConversionDecl *Conv;
FunctionTemplateDecl *ConvTemplate;
if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D)))
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
Conv = cast<CXXConversionDecl>(D);
if (ConvTemplate)
S.AddTemplateConversionCandidate(
ConvTemplate, FoundDecl, ActingContext, From, ToType,
CandidateSet, AllowObjCConversionOnExplicit,
AllowExplicit != AllowedExplicit::None);
else
S.AddConversionCandidate(Conv, FoundDecl, ActingContext, From, ToType,
CandidateSet, AllowObjCConversionOnExplicit,
AllowExplicit != AllowedExplicit::None);
}
}
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (auto Result =
CandidateSet.BestViableFunction(S, From->getBeginLoc(), Best)) {
case OR_Success:
case OR_Deleted:
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Best->Function)) {
QualType ThisType = Constructor->getThisType();
if (isa<InitListExpr>(From)) {
User.Before.setAsIdentityConversion();
} else {
if (Best->Conversions[0].isEllipsis())
User.EllipsisConversion = true;
else {
User.Before = Best->Conversions[0].Standard;
User.EllipsisConversion = false;
}
}
User.HadMultipleCandidates = HadMultipleCandidates;
User.ConversionFunction = Constructor;
User.FoundConversionFunction = Best->FoundDecl;
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->castAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
return Result;
}
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
User.Before = Best->Conversions[0].Standard;
User.HadMultipleCandidates = HadMultipleCandidates;
User.ConversionFunction = Conversion;
User.FoundConversionFunction = Best->FoundDecl;
User.EllipsisConversion = false;
User.After = Best->FinalConversion;
return Result;
}
llvm_unreachable("Not a constructor or conversion function?");
case OR_No_Viable_Function:
return OR_No_Viable_Function;
case OR_Ambiguous:
return OR_Ambiguous;
}
llvm_unreachable("Invalid OverloadResult!");
}
bool
Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet(From->getExprLoc(),
OverloadCandidateSet::CSK_Normal);
OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, AllowedExplicit::None, false);
if (!(OvResult == OR_Ambiguous ||
(OvResult == OR_No_Viable_Function && !CandidateSet.empty())))
return false;
auto Cands = CandidateSet.CompleteCandidates(
*this,
OvResult == OR_Ambiguous ? OCD_AmbiguousCandidates : OCD_AllCandidates,
From);
if (OvResult == OR_Ambiguous)
Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition)
<< From->getType() << ToType << From->getSourceRange();
else { if (!RequireCompleteType(From->getBeginLoc(), ToType,
diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
Diag(From->getBeginLoc(), diag::err_typecheck_nonviable_condition)
<< false << From->getType() << From->getSourceRange() << ToType;
}
CandidateSet.NoteCandidates(
*this, From, Cands);
return true;
}
static const FunctionType *
getConversionOpReturnTyAsFunction(CXXConversionDecl *Conv) {
const FunctionType *ConvFuncTy = Conv->getType()->castAs<FunctionType>();
const PointerType *RetPtrTy =
ConvFuncTy->getReturnType()->getAs<PointerType>();
if (!RetPtrTy)
return nullptr;
return RetPtrTy->getPointeeType()->getAs<FunctionType>();
}
static ImplicitConversionSequence::CompareKind
compareConversionFunctions(Sema &S, FunctionDecl *Function1,
FunctionDecl *Function2) {
CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1);
CXXConversionDecl *Conv2 = dyn_cast_or_null<CXXConversionDecl>(Function2);
if (!Conv1 || !Conv2)
return ImplicitConversionSequence::Indistinguishable;
if (!Conv1->getParent()->isLambda() || !Conv2->getParent()->isLambda())
return ImplicitConversionSequence::Indistinguishable;
if (S.getLangOpts().ObjC && S.getLangOpts().CPlusPlus11) {
bool Block1 = Conv1->getConversionType()->isBlockPointerType();
bool Block2 = Conv2->getConversionType()->isBlockPointerType();
if (Block1 != Block2)
return Block1 ? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
}
const FunctionType *Conv1FuncRet = getConversionOpReturnTyAsFunction(Conv1);
const FunctionType *Conv2FuncRet = getConversionOpReturnTyAsFunction(Conv2);
if (Conv1FuncRet && Conv2FuncRet &&
Conv1FuncRet->getCallConv() != Conv2FuncRet->getCallConv()) {
CallingConv Conv1CC = Conv1FuncRet->getCallConv();
CallingConv Conv2CC = Conv2FuncRet->getCallConv();
CXXMethodDecl *CallOp = Conv2->getParent()->getLambdaCallOperator();
const auto *CallOpProto = CallOp->getType()->castAs<FunctionProtoType>();
CallingConv CallOpCC =
CallOp->getType()->castAs<FunctionType>()->getCallConv();
CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
CallOpProto->isVariadic(), false);
CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
CallOpProto->isVariadic(), true);
CallingConv PrefOrder[] = {DefaultFree, DefaultMember, CallOpCC};
for (CallingConv CC : PrefOrder) {
if (Conv1CC == CC)
return ImplicitConversionSequence::Better;
if (Conv2CC == CC)
return ImplicitConversionSequence::Worse;
}
}
return ImplicitConversionSequence::Indistinguishable;
}
static bool hasDeprecatedStringLiteralToCharPtrConversion(
const ImplicitConversionSequence &ICS) {
return (ICS.isStandard() && ICS.Standard.DeprecatedStringLiteralToCharPtr) ||
(ICS.isUserDefined() &&
ICS.UserDefined.Before.DeprecatedStringLiteralToCharPtr);
}
static ImplicitConversionSequence::CompareKind
CompareImplicitConversionSequences(Sema &S, SourceLocation Loc,
const ImplicitConversionSequence& ICS1,
const ImplicitConversionSequence& ICS2)
{
if (S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
hasDeprecatedStringLiteralToCharPtrConversion(ICS1) !=
hasDeprecatedStringLiteralToCharPtrConversion(ICS2) &&
ICS1.isBad() == ICS2.isBad())
return hasDeprecatedStringLiteralToCharPtrConversion(ICS1)
? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
if (ICS1.getKindRank() < ICS2.getKindRank())
return ImplicitConversionSequence::Better;
if (ICS2.getKindRank() < ICS1.getKindRank())
return ImplicitConversionSequence::Worse;
if (ICS1.getKind() != ICS2.getKind())
return ImplicitConversionSequence::Indistinguishable;
ImplicitConversionSequence::CompareKind Result =
ImplicitConversionSequence::Indistinguishable;
if (!ICS1.isBad()) {
bool StdInit1 = false, StdInit2 = false;
if (ICS1.hasInitializerListContainerType())
StdInit1 = S.isStdInitializerList(ICS1.getInitializerListContainerType(),
nullptr);
if (ICS2.hasInitializerListContainerType())
StdInit2 = S.isStdInitializerList(ICS2.getInitializerListContainerType(),
nullptr);
if (StdInit1 != StdInit2)
return StdInit1 ? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
if (ICS1.hasInitializerListContainerType() &&
ICS2.hasInitializerListContainerType())
if (auto *CAT1 = S.Context.getAsConstantArrayType(
ICS1.getInitializerListContainerType()))
if (auto *CAT2 = S.Context.getAsConstantArrayType(
ICS2.getInitializerListContainerType())) {
if (S.Context.hasSameUnqualifiedType(CAT1->getElementType(),
CAT2->getElementType())) {
if (CAT1->getSize() != CAT2->getSize())
return CAT1->getSize().ult(CAT2->getSize())
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
if (ICS1.isInitializerListOfIncompleteArray() !=
ICS2.isInitializerListOfIncompleteArray())
return ICS2.isInitializerListOfIncompleteArray()
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}
}
}
if (ICS1.isStandard())
Result = CompareStandardConversionSequences(S, Loc,
ICS1.Standard, ICS2.Standard);
else if (ICS1.isUserDefined()) {
if (ICS1.UserDefined.ConversionFunction ==
ICS2.UserDefined.ConversionFunction)
Result = CompareStandardConversionSequences(S, Loc,
ICS1.UserDefined.After,
ICS2.UserDefined.After);
else
Result = compareConversionFunctions(S,
ICS1.UserDefined.ConversionFunction,
ICS2.UserDefined.ConversionFunction);
}
return Result;
}
static ImplicitConversionSequence::CompareKind
compareStandardConversionSubsets(ASTContext &Context,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion())
return ImplicitConversionSequence::Better;
else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion())
return ImplicitConversionSequence::Worse;
if (SCS1.Second != SCS2.Second) {
if (SCS1.Second == ICK_Identity)
Result = ImplicitConversionSequence::Better;
else if (SCS2.Second == ICK_Identity)
Result = ImplicitConversionSequence::Worse;
else
return ImplicitConversionSequence::Indistinguishable;
} else if (!Context.hasSimilarType(SCS1.getToType(1), SCS2.getToType(1)))
return ImplicitConversionSequence::Indistinguishable;
if (SCS1.Third == SCS2.Third) {
return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result
: ImplicitConversionSequence::Indistinguishable;
}
if (SCS1.Third == ICK_Identity)
return Result == ImplicitConversionSequence::Worse
? ImplicitConversionSequence::Indistinguishable
: ImplicitConversionSequence::Better;
if (SCS2.Third == ICK_Identity)
return Result == ImplicitConversionSequence::Better
? ImplicitConversionSequence::Indistinguishable
: ImplicitConversionSequence::Worse;
return ImplicitConversionSequence::Indistinguishable;
}
static bool
isBetterReferenceBindingKind(const StandardConversionSequence &SCS1,
const StandardConversionSequence &SCS2) {
if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier ||
SCS2.BindsImplicitObjectArgumentWithoutRefQualifier)
return false;
return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue &&
SCS2.IsLvalueReference) ||
(SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue &&
!SCS2.IsLvalueReference && SCS2.BindsToFunctionLvalue);
}
enum class FixedEnumPromotion {
None,
ToUnderlyingType,
ToPromotedUnderlyingType
};
static FixedEnumPromotion
getFixedEnumPromtion(Sema &S, const StandardConversionSequence &SCS) {
if (SCS.Second != ICK_Integral_Promotion)
return FixedEnumPromotion::None;
QualType FromType = SCS.getFromType();
if (!FromType->isEnumeralType())
return FixedEnumPromotion::None;
EnumDecl *Enum = FromType->castAs<EnumType>()->getDecl();
if (!Enum->isFixed())
return FixedEnumPromotion::None;
QualType UnderlyingType = Enum->getIntegerType();
if (S.Context.hasSameType(SCS.getToType(1), UnderlyingType))
return FixedEnumPromotion::ToUnderlyingType;
return FixedEnumPromotion::ToPromotedUnderlyingType;
}
static ImplicitConversionSequence::CompareKind
CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2)
{
if (ImplicitConversionSequence::CompareKind CK
= compareStandardConversionSubsets(S.Context, SCS1, SCS2))
return CK;
ImplicitConversionRank Rank1 = SCS1.getRank();
ImplicitConversionRank Rank2 = SCS2.getRank();
if (Rank1 < Rank2)
return ImplicitConversionSequence::Better;
else if (Rank2 < Rank1)
return ImplicitConversionSequence::Worse;
if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool())
return SCS2.isPointerConversionToBool()
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
FixedEnumPromotion FEP1 = getFixedEnumPromtion(S, SCS1);
FixedEnumPromotion FEP2 = getFixedEnumPromtion(S, SCS2);
if (FEP1 != FixedEnumPromotion::None && FEP2 != FixedEnumPromotion::None &&
FEP1 != FEP2)
return FEP1 == FixedEnumPromotion::ToUnderlyingType
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
bool SCS1ConvertsToVoid
= SCS1.isPointerConversionToVoidPointer(S.Context);
bool SCS2ConvertsToVoid
= SCS2.isPointerConversionToVoidPointer(S.Context);
if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) {
return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
} else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) {
if (ImplicitConversionSequence::CompareKind DerivedCK
= CompareDerivedToBaseConversions(S, Loc, SCS1, SCS2))
return DerivedCK;
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid &&
!S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) {
QualType FromType1 = SCS1.getFromType();
QualType FromType2 = SCS2.getFromType();
if (SCS1.First == ICK_Array_To_Pointer)
FromType1 = S.Context.getArrayDecayedType(FromType1);
if (SCS2.First == ICK_Array_To_Pointer)
FromType2 = S.Context.getArrayDecayedType(FromType2);
QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType();
QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType();
if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
const ObjCObjectPointerType* FromObjCPtr1
= FromType1->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType* FromObjCPtr2
= FromType2->getAs<ObjCObjectPointerType>();
if (FromObjCPtr1 && FromObjCPtr2) {
bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1,
FromObjCPtr2);
bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2,
FromObjCPtr1);
if (AssignLeft != AssignRight) {
return AssignLeft? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}
}
}
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
if (isBetterReferenceBindingKind(SCS1, SCS2))
return ImplicitConversionSequence::Better;
else if (isBetterReferenceBindingKind(SCS2, SCS1))
return ImplicitConversionSequence::Worse;
}
if (ImplicitConversionSequence::CompareKind QualCK
= CompareQualificationConversions(S, SCS1, SCS2))
return QualCK;
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
QualType T1 = SCS1.getToType(2);
QualType T2 = SCS2.getToType(2);
T1 = S.Context.getCanonicalType(T1);
T2 = S.Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
if (UnqualT1 == UnqualT2) {
if (SCS1.ObjCLifetimeConversionBinding !=
SCS2.ObjCLifetimeConversionBinding) {
return SCS1.ObjCLifetimeConversionBinding
? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
}
if (isa<ArrayType>(T1) && T1Quals)
T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
if (isa<ArrayType>(T2) && T2Quals)
T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
if (T2.isMoreQualifiedThan(T1))
return ImplicitConversionSequence::Better;
if (T1.isMoreQualifiedThan(T2))
return ImplicitConversionSequence::Worse;
}
}
if (S.getLangOpts().MSVCCompat &&
!S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2019_8) &&
SCS1.Second == ICK_Integral_Conversion &&
SCS2.Second == ICK_Floating_Integral &&
S.Context.getTypeSize(SCS1.getFromType()) ==
S.Context.getTypeSize(SCS1.getToType(2)))
return ImplicitConversionSequence::Better;
if (SCS1.Second == ICK_Vector_Conversion &&
SCS2.Second == ICK_Vector_Conversion) {
bool SCS1IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes(
SCS1.getFromType(), SCS1.getToType(2));
bool SCS2IsCompatibleVectorConversion = S.Context.areCompatibleVectorTypes(
SCS2.getFromType(), SCS2.getToType(2));
if (SCS1IsCompatibleVectorConversion != SCS2IsCompatibleVectorConversion)
return SCS1IsCompatibleVectorConversion
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}
if (SCS1.Second == ICK_SVE_Vector_Conversion &&
SCS2.Second == ICK_SVE_Vector_Conversion) {
bool SCS1IsCompatibleSVEVectorConversion =
S.Context.areCompatibleSveTypes(SCS1.getFromType(), SCS1.getToType(2));
bool SCS2IsCompatibleSVEVectorConversion =
S.Context.areCompatibleSveTypes(SCS2.getFromType(), SCS2.getToType(2));
if (SCS1IsCompatibleSVEVectorConversion !=
SCS2IsCompatibleSVEVectorConversion)
return SCS1IsCompatibleSVEVectorConversion
? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}
return ImplicitConversionSequence::Indistinguishable;
}
static ImplicitConversionSequence::CompareKind
CompareQualificationConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second ||
SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification)
return ImplicitConversionSequence::Indistinguishable;
QualType T1 = SCS1.getToType(2);
QualType T2 = SCS2.getToType(2);
T1 = S.Context.getCanonicalType(T1);
T2 = S.Context.getCanonicalType(T2);
assert(!T1->isReferenceType() && !T2->isReferenceType());
Qualifiers T1Quals, T2Quals;
QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
if (UnqualT1 == UnqualT2)
return ImplicitConversionSequence::Indistinguishable;
bool CanPick1 = !SCS1.DeprecatedStringLiteralToCharPtr;
bool CanPick2 = !SCS2.DeprecatedStringLiteralToCharPtr;
if (SCS1.QualificationIncludesObjCLifetime &&
!SCS2.QualificationIncludesObjCLifetime)
CanPick1 = false;
if (SCS2.QualificationIncludesObjCLifetime &&
!SCS1.QualificationIncludesObjCLifetime)
CanPick2 = false;
bool ObjCLifetimeConversion;
if (CanPick1 &&
!S.IsQualificationConversion(T1, T2, false, ObjCLifetimeConversion))
CanPick1 = false;
if (CanPick2 &&
!S.IsQualificationConversion(T2, T1, false, ObjCLifetimeConversion))
CanPick2 = false;
if (CanPick1 != CanPick2)
return CanPick1 ? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
return ImplicitConversionSequence::Indistinguishable;
}
static ImplicitConversionSequence::CompareKind
CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
QualType FromType1 = SCS1.getFromType();
QualType ToType1 = SCS1.getToType(1);
QualType FromType2 = SCS2.getFromType();
QualType ToType2 = SCS2.getToType(1);
if (SCS1.First == ICK_Array_To_Pointer)
FromType1 = S.Context.getArrayDecayedType(FromType1);
if (SCS2.First == ICK_Array_To_Pointer)
FromType2 = S.Context.getArrayDecayedType(FromType2);
FromType1 = S.Context.getCanonicalType(FromType1);
ToType1 = S.Context.getCanonicalType(ToType1);
FromType2 = S.Context.getCanonicalType(FromType2);
ToType2 = S.Context.getCanonicalType(ToType2);
if (SCS1.Second == ICK_Pointer_Conversion &&
SCS2.Second == ICK_Pointer_Conversion &&
FromType1->isPointerType() && FromType2->isPointerType() &&
ToType1->isPointerType() && ToType2->isPointerType()) {
QualType FromPointee1 =
FromType1->castAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType ToPointee1 =
ToType1->castAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType FromPointee2 =
FromType2->castAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType ToPointee2 =
ToType2->castAs<PointerType>()->getPointeeType().getUnqualifiedType();
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
}
if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Worse;
}
} else if (SCS1.Second == ICK_Pointer_Conversion &&
SCS2.Second == ICK_Pointer_Conversion) {
const ObjCObjectPointerType *FromPtr1
= FromType1->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *FromPtr2
= FromType2->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *ToPtr1
= ToType1->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *ToPtr2
= ToType2->getAs<ObjCObjectPointerType>();
if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) {
bool FromAssignLeft
= S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2);
bool FromAssignRight
= S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1);
bool ToAssignLeft
= S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2);
bool ToAssignRight
= S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1);
if (ToPtr1->isObjCIdType() &&
(ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl()))
return ImplicitConversionSequence::Worse;
if (ToPtr2->isObjCIdType() &&
(ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl()))
return ImplicitConversionSequence::Better;
if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl())
return ImplicitConversionSequence::Worse;
if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl())
return ImplicitConversionSequence::Better;
if (ToPtr1->isObjCClassType() &&
(ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl()))
return ImplicitConversionSequence::Worse;
if (ToPtr2->isObjCClassType() &&
(ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl()))
return ImplicitConversionSequence::Better;
if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl())
return ImplicitConversionSequence::Worse;
if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl())
return ImplicitConversionSequence::Better;
if (S.Context.hasSameType(FromType1, FromType2) &&
!FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() &&
(ToAssignLeft != ToAssignRight)) {
if (FromPtr1->isSpecialized()) {
bool IsFirstSame =
FromPtr1->getInterfaceDecl() == ToPtr1->getInterfaceDecl();
bool IsSecondSame =
FromPtr1->getInterfaceDecl() == ToPtr2->getInterfaceDecl();
if (IsFirstSame) {
if (!IsSecondSame)
return ImplicitConversionSequence::Better;
} else if (IsSecondSame)
return ImplicitConversionSequence::Worse;
}
return ToAssignLeft? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
}
if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) &&
(FromAssignLeft != FromAssignRight))
return FromAssignLeft? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}
}
if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member &&
FromType1->isMemberPointerType() && FromType2->isMemberPointerType() &&
ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) {
const auto *FromMemPointer1 = FromType1->castAs<MemberPointerType>();
const auto *ToMemPointer1 = ToType1->castAs<MemberPointerType>();
const auto *FromMemPointer2 = FromType2->castAs<MemberPointerType>();
const auto *ToMemPointer2 = ToType2->castAs<MemberPointerType>();
const Type *FromPointeeType1 = FromMemPointer1->getClass();
const Type *ToPointeeType1 = ToMemPointer1->getClass();
const Type *FromPointeeType2 = FromMemPointer2->getClass();
const Type *ToPointeeType2 = ToMemPointer2->getClass();
QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType();
QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType();
QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType();
QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType();
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
if (S.IsDerivedFrom(Loc, ToPointee1, ToPointee2))
return ImplicitConversionSequence::Worse;
else if (S.IsDerivedFrom(Loc, ToPointee2, ToPointee1))
return ImplicitConversionSequence::Better;
}
if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
if (S.IsDerivedFrom(Loc, FromPointee1, FromPointee2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(Loc, FromPointee2, FromPointee1))
return ImplicitConversionSequence::Worse;
}
}
if (SCS1.Second == ICK_Derived_To_Base) {
if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
!S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (S.IsDerivedFrom(Loc, ToType1, ToType2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(Loc, ToType2, ToType1))
return ImplicitConversionSequence::Worse;
}
if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (S.IsDerivedFrom(Loc, FromType2, FromType1))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(Loc, FromType1, FromType2))
return ImplicitConversionSequence::Worse;
}
}
return ImplicitConversionSequence::Indistinguishable;
}
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;
Qualifiers Q;
T = Ctx.getUnqualifiedArrayType(T, Q);
Q.removeUnaligned();
return Ctx.getQualifiedType(T, Q);
}
Sema::ReferenceCompareResult
Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
ReferenceConversions *ConvOut) {
assert(!OrigT1->isReferenceType() &&
"T1 must be the pointee type of the reference type");
assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
QualType T1 = Context.getCanonicalType(OrigT1);
QualType T2 = Context.getCanonicalType(OrigT2);
Qualifiers T1Quals, T2Quals;
QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
ReferenceConversions ConvTmp;
ReferenceConversions &Conv = ConvOut ? *ConvOut : ConvTmp;
Conv = ReferenceConversions();
QualType ConvertedT2;
if (UnqualT1 == UnqualT2) {
} else if (isCompleteType(Loc, OrigT2) &&
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
IsDerivedFrom(Loc, UnqualT2, UnqualT1))
Conv |= ReferenceConversions::DerivedToBase;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
Conv |= ReferenceConversions::ObjC;
else if (UnqualT2->isFunctionType() &&
IsFunctionConversion(UnqualT2, UnqualT1, ConvertedT2)) {
Conv |= ReferenceConversions::Function;
return Ref_Compatible;
}
bool ConvertedReferent = Conv != 0;
bool PreviousToQualsIncludeConst = true;
bool TopLevel = true;
do {
if (T1 == T2)
break;
Conv |= ReferenceConversions::Qualification;
if (!TopLevel)
Conv |= ReferenceConversions::NestedQualification;
T1 = withoutUnaligned(Context, T1);
T2 = withoutUnaligned(Context, T2);
bool ObjCLifetimeConversion = false;
if (!isQualificationConversionStep(T2, T1, false, TopLevel,
PreviousToQualsIncludeConst,
ObjCLifetimeConversion))
return (ConvertedReferent || Context.hasSimilarType(T1, T2))
? Ref_Related
: Ref_Incompatible;
if (ObjCLifetimeConversion)
Conv |= ReferenceConversions::ObjCLifetime;
TopLevel = false;
} while (Context.UnwrapSimilarTypes(T1, T2));
return (ConvertedReferent || Context.hasSameUnqualifiedType(T1, T2))
? Ref_Compatible
: Ref_Incompatible;
}
static bool
FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
QualType DeclType, SourceLocation DeclLoc,
Expr *Init, QualType T2, bool AllowRvalues,
bool AllowExplicit) {
assert(T2->isRecordType() && "Can only find conversions of record types.");
auto *T2RecordDecl = cast<CXXRecordDecl>(T2->castAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet(
DeclLoc, OverloadCandidateSet::CSK_InitByUserDefinedConversion);
const auto &Conversions = T2RecordDecl->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
FunctionTemplateDecl *ConvTemplate
= dyn_cast<FunctionTemplateDecl>(D);
CXXConversionDecl *Conv;
if (ConvTemplate)
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
Conv = cast<CXXConversionDecl>(D);
if (AllowRvalues) {
if (!ConvTemplate && DeclType->isRValueReferenceType()) {
const ReferenceType *RefType
= Conv->getConversionType()->getAs<LValueReferenceType>();
if (RefType && !RefType->getPointeeType()->isFunctionType())
continue;
}
if (!ConvTemplate &&
S.CompareReferenceRelationship(
DeclLoc,
Conv->getConversionType()
.getNonReferenceType()
.getUnqualifiedType(),
DeclType.getNonReferenceType().getUnqualifiedType()) ==
Sema::Ref_Incompatible)
continue;
} else {
const ReferenceType *RefType =
Conv->getConversionType()->getAs<ReferenceType>();
if (!RefType ||
(!RefType->isLValueReferenceType() &&
!RefType->getPointeeType()->isFunctionType()))
continue;
}
if (ConvTemplate)
S.AddTemplateConversionCandidate(
ConvTemplate, I.getPair(), ActingDC, Init, DeclType, CandidateSet,
false, AllowExplicit);
else
S.AddConversionCandidate(
Conv, I.getPair(), ActingDC, Init, DeclType, CandidateSet,
false, AllowExplicit);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
case OR_Success:
if (!Best->FinalConversion.DirectBinding)
return false;
ICS.setUserDefined();
ICS.UserDefined.Before = Best->Conversions[0].Standard;
ICS.UserDefined.After = Best->FinalConversion;
ICS.UserDefined.HadMultipleCandidates = HadMultipleCandidates;
ICS.UserDefined.ConversionFunction = Best->Function;
ICS.UserDefined.FoundConversionFunction = Best->FoundDecl;
ICS.UserDefined.EllipsisConversion = false;
assert(ICS.UserDefined.After.ReferenceBinding &&
ICS.UserDefined.After.DirectBinding &&
"Expected a direct reference binding!");
return true;
case OR_Ambiguous:
ICS.setAmbiguous();
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand)
if (Cand->Best)
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
return true;
case OR_No_Viable_Function:
case OR_Deleted:
return false;
}
llvm_unreachable("Invalid OverloadResult!");
}
static ImplicitConversionSequence
TryReferenceInit(Sema &S, Expr *Init, QualType DeclType,
SourceLocation DeclLoc,
bool SuppressUserConversions,
bool AllowExplicit) {
assert(DeclType->isReferenceType() && "Reference init needs a reference");
ImplicitConversionSequence ICS;
ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
QualType T1 = DeclType->castAs<ReferenceType>()->getPointeeType();
QualType T2 = Init->getType();
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
DeclAccessPair Found;
if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType,
false, Found))
T2 = Fn->getType();
}
bool isRValRef = DeclType->isRValueReferenceType();
Expr::Classification InitCategory = Init->Classify(S.Context);
Sema::ReferenceConversions RefConv;
Sema::ReferenceCompareResult RefRelationship =
S.CompareReferenceRelationship(DeclLoc, T1, T2, &RefConv);
auto SetAsReferenceBinding = [&](bool BindsDirectly) {
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
ICS.Standard.Second = (RefConv & Sema::ReferenceConversions::DerivedToBase)
? ICK_Derived_To_Base
: (RefConv & Sema::ReferenceConversions::ObjC)
? ICK_Compatible_Conversion
: ICK_Identity;
ICS.Standard.Third = (RefConv &
Sema::ReferenceConversions::NestedQualification)
? ICK_Qualification
: ICK_Identity;
ICS.Standard.setFromType(T2);
ICS.Standard.setToType(0, T2);
ICS.Standard.setToType(1, T1);
ICS.Standard.setToType(2, T1);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = BindsDirectly;
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding =
(RefConv & Sema::ReferenceConversions::ObjCLifetime) != 0;
ICS.Standard.CopyConstructor = nullptr;
ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
};
if (!isRValRef) {
if (InitCategory.isLValue() && RefRelationship == Sema::Ref_Compatible) {
SetAsReferenceBinding(true);
return ICS;
}
if (!SuppressUserConversions && T2->isRecordType() &&
S.isCompleteType(DeclLoc, T2) &&
RefRelationship == Sema::Ref_Incompatible) {
if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, false,
AllowExplicit))
return ICS;
}
}
if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified())) {
if (InitCategory.isRValue() && RefRelationship != Sema::Ref_Incompatible)
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init, DeclType);
return ICS;
}
if (RefRelationship == Sema::Ref_Compatible &&
(InitCategory.isXValue() ||
(InitCategory.isPRValue() &&
(T2->isRecordType() || T2->isArrayType())) ||
(InitCategory.isLValue() && T2->isFunctionType()))) {
SetAsReferenceBinding(S.getLangOpts().CPlusPlus11 ||
!(InitCategory.isPRValue() || T2->isRecordType()));
return ICS;
}
if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
T2->isRecordType() && S.isCompleteType(DeclLoc, T2) &&
FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, true,
AllowExplicit)) {
if (ICS.isUserDefined() && isRValRef &&
ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue)
ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
return ICS;
}
if (T1->isFunctionType())
return ICS;
if (RefRelationship == Sema::Ref_Related) {
Qualifiers T1Quals = T1.getQualifiers();
Qualifiers T2Quals = T2.getQualifiers();
T1Quals.removeObjCGCAttr();
T1Quals.removeObjCLifetime();
T2Quals.removeObjCGCAttr();
T2Quals.removeObjCLifetime();
T1Quals.removeUnaligned();
T2Quals.removeUnaligned();
if (!T1Quals.compatiblyIncludes(T2Quals))
return ICS;
}
if (SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
(T1->isRecordType() || T2->isRecordType()))
return ICS;
if (RefRelationship >= Sema::Ref_Related && isRValRef &&
Init->Classify(S.Context).isLValue()) {
ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, Init, DeclType);
return ICS;
}
ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
AllowedExplicit::None,
false,
false,
false,
false);
if (ICS.isStandard()) {
ICS.Standard.ReferenceBinding = true;
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = false;
ICS.Standard.BindsToRvalue = true;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = false;
} else if (ICS.isUserDefined()) {
const ReferenceType *LValRefType =
ICS.UserDefined.ConversionFunction->getReturnType()
->getAs<LValueReferenceType>();
if (isRValRef && LValRefType) {
ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
return ICS;
}
ICS.UserDefined.After.ReferenceBinding = true;
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
ICS.UserDefined.After.BindsToFunctionLvalue = false;
ICS.UserDefined.After.BindsToRvalue = !LValRefType;
ICS.UserDefined.After.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.UserDefined.After.ObjCLifetimeConversionBinding = false;
}
return ICS;
}
static ImplicitConversionSequence
TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
bool InOverloadResolution,
bool AllowObjCWritebackConversion,
bool AllowExplicit = false);
static ImplicitConversionSequence
TryListConversion(Sema &S, InitListExpr *From, QualType ToType,
bool SuppressUserConversions,
bool InOverloadResolution,
bool AllowObjCWritebackConversion) {
ImplicitConversionSequence Result;
Result.setBad(BadConversionSequence::no_conversion, From, ToType);
QualType InitTy = ToType;
const ArrayType *AT = S.Context.getAsArrayType(ToType);
if (AT && S.getLangOpts().CPlusPlus20)
if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT))
InitTy = IAT->getElementType();
if (!S.isCompleteType(From->getBeginLoc(), InitTy))
return Result;
if (From->getNumInits() == 1) {
if (ToType->isRecordType()) {
QualType InitType = From->getInit(0)->getType();
if (S.Context.hasSameUnqualifiedType(InitType, ToType) ||
S.IsDerivedFrom(From->getBeginLoc(), InitType, ToType))
return TryCopyInitialization(S, From->getInit(0), ToType,
SuppressUserConversions,
InOverloadResolution,
AllowObjCWritebackConversion);
}
if (AT && S.IsStringInit(From->getInit(0), AT)) {
InitializedEntity Entity =
InitializedEntity::InitializeParameter(S.Context, ToType,
false);
if (S.CanPerformCopyInitialization(Entity, From)) {
Result.setStandard();
Result.Standard.setAsIdentityConversion();
Result.Standard.setFromType(ToType);
Result.Standard.setAllToTypes(ToType);
return Result;
}
}
}
if (AT || S.isStdInitializerList(ToType, &InitTy)) {
unsigned e = From->getNumInits();
ImplicitConversionSequence DfltElt;
DfltElt.setBad(BadConversionSequence::no_conversion, QualType(),
QualType());
QualType ContTy = ToType;
bool IsUnbounded = false;
if (AT) {
InitTy = AT->getElementType();
if (ConstantArrayType const *CT = dyn_cast<ConstantArrayType>(AT)) {
if (CT->getSize().ult(e)) {
Result.setBad(BadConversionSequence::too_many_initializers, From,
ToType);
Result.setInitializerListContainerType(ContTy, IsUnbounded);
return Result;
}
if (CT->getSize().ugt(e)) {
InitListExpr EmptyList(S.Context, From->getEndLoc(), None,
From->getEndLoc());
EmptyList.setType(S.Context.VoidTy);
DfltElt = TryListConversion(
S, &EmptyList, InitTy, SuppressUserConversions,
InOverloadResolution, AllowObjCWritebackConversion);
if (DfltElt.isBad()) {
Result.setBad(BadConversionSequence::too_few_initializers, From,
ToType);
Result.setInitializerListContainerType(ContTy, IsUnbounded);
return Result;
}
}
} else {
assert(isa<IncompleteArrayType>(AT) && "Expected incomplete array");
IsUnbounded = true;
if (!e) {
Result.setBad(BadConversionSequence::too_few_initializers, From,
ToType);
Result.setInitializerListContainerType(ContTy, IsUnbounded);
return Result;
}
llvm::APInt Size(S.Context.getTypeSize(S.Context.getSizeType()), e);
ContTy = S.Context.getConstantArrayType(InitTy, Size, nullptr,
ArrayType::Normal, 0);
}
}
Result.setStandard();
Result.Standard.setAsIdentityConversion();
Result.Standard.setFromType(InitTy);
Result.Standard.setAllToTypes(InitTy);
for (unsigned i = 0; i < e; ++i) {
Expr *Init = From->getInit(i);
ImplicitConversionSequence ICS = TryCopyInitialization(
S, Init, InitTy, SuppressUserConversions, InOverloadResolution,
AllowObjCWritebackConversion);
if (CompareImplicitConversionSequences(S, From->getBeginLoc(), ICS,
Result) ==
ImplicitConversionSequence::Worse) {
Result = ICS;
if (Result.isBad()) {
Result.setInitializerListContainerType(ContTy, IsUnbounded);
return Result;
}
}
}
if (!DfltElt.isBad() && CompareImplicitConversionSequences(
S, From->getEndLoc(), DfltElt, Result) ==
ImplicitConversionSequence::Worse)
Result = DfltElt;
Result.setInitializerListContainerType(ContTy, IsUnbounded);
return Result;
}
if (ToType->isRecordType() && !ToType->isAggregateType()) {
return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
AllowedExplicit::None,
InOverloadResolution, false,
AllowObjCWritebackConversion,
false);
}
if (ToType->isAggregateType()) {
InitializedEntity Entity =
InitializedEntity::InitializeParameter(S.Context, ToType,
false);
if (S.CanPerformAggregateInitializationForOverloadResolution(Entity,
From)) {
Result.setUserDefined();
Result.UserDefined.Before.setAsIdentityConversion();
Result.UserDefined.Before.setFromType(QualType());
Result.UserDefined.Before.setAllToTypes(QualType());
Result.UserDefined.After.setAsIdentityConversion();
Result.UserDefined.After.setFromType(ToType);
Result.UserDefined.After.setAllToTypes(ToType);
Result.UserDefined.ConversionFunction = nullptr;
}
return Result;
}
if (ToType->isReferenceType()) {
QualType T1 = ToType->castAs<ReferenceType>()->getPointeeType();
if (From->getNumInits() == 1) {
Expr *Init = From->getInit(0);
QualType T2 = Init->getType();
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
DeclAccessPair Found;
if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
Init, ToType, false, Found))
T2 = Fn->getType();
}
Sema::ReferenceCompareResult RefRelationship =
S.CompareReferenceRelationship(From->getBeginLoc(), T1, T2);
if (RefRelationship >= Sema::Ref_Related) {
return TryReferenceInit(S, Init, ToType, From->getBeginLoc(),
SuppressUserConversions,
false);
}
}
Result = TryListConversion(S, From, T1, SuppressUserConversions,
InOverloadResolution,
AllowObjCWritebackConversion);
if (Result.isFailure())
return Result;
assert(!Result.isEllipsis() &&
"Sub-initialization cannot result in ellipsis conversion.");
if (ToType->isRValueReferenceType() ||
(T1.isConstQualified() && !T1.isVolatileQualified())) {
StandardConversionSequence &SCS = Result.isStandard() ? Result.Standard :
Result.UserDefined.After;
SCS.ReferenceBinding = true;
SCS.IsLvalueReference = ToType->isLValueReferenceType();
SCS.BindsToRvalue = true;
SCS.BindsToFunctionLvalue = false;
SCS.BindsImplicitObjectArgumentWithoutRefQualifier = false;
SCS.ObjCLifetimeConversionBinding = false;
} else
Result.setBad(BadConversionSequence::lvalue_ref_to_rvalue,
From, ToType);
return Result;
}
if (!ToType->isRecordType()) {
unsigned NumInits = From->getNumInits();
if (NumInits == 1 && !isa<InitListExpr>(From->getInit(0)))
Result = TryCopyInitialization(S, From->getInit(0), ToType,
SuppressUserConversions,
InOverloadResolution,
AllowObjCWritebackConversion);
else if (NumInits == 0) {
Result.setStandard();
Result.Standard.setAsIdentityConversion();
Result.Standard.setFromType(ToType);
Result.Standard.setAllToTypes(ToType);
}
return Result;
}
return Result;
}
static ImplicitConversionSequence
TryCopyInitialization(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
bool InOverloadResolution,
bool AllowObjCWritebackConversion,
bool AllowExplicit) {
if (InitListExpr *FromInitList = dyn_cast<InitListExpr>(From))
return TryListConversion(S, FromInitList, ToType, SuppressUserConversions,
InOverloadResolution,AllowObjCWritebackConversion);
if (ToType->isReferenceType())
return TryReferenceInit(S, From, ToType,
From->getBeginLoc(),
SuppressUserConversions, AllowExplicit);
return TryImplicitConversion(S, From, ToType,
SuppressUserConversions,
AllowedExplicit::None,
InOverloadResolution,
false,
AllowObjCWritebackConversion,
false);
}
static bool TryCopyInitialization(const CanQualType FromQTy,
const CanQualType ToQTy,
Sema &S,
SourceLocation Loc,
ExprValueKind FromVK) {
OpaqueValueExpr TmpExpr(Loc, FromQTy, FromVK);
ImplicitConversionSequence ICS =
TryCopyInitialization(S, &TmpExpr, ToQTy, true, true, false);
return !ICS.isBad();
}
static ImplicitConversionSequence
TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
Expr::Classification FromClassification,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
Qualifiers Quals = Method->getMethodQualifiers();
if (isa<CXXDestructorDecl>(Method)) {
Quals.addConst();
Quals.addVolatile();
}
QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals);
ImplicitConversionSequence ICS;
if (const PointerType *PT = FromType->getAs<PointerType>()) {
FromType = PT->getPointeeType();
assert(FromClassification.isLValue());
}
assert(FromType->isRecordType());
QualType FromTypeCanon = S.Context.getCanonicalType(FromType);
if (ImplicitParamType.getCVRQualifiers()
!= FromTypeCanon.getLocalCVRQualifiers() &&
!ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
ICS.setBad(BadConversionSequence::bad_qualifiers,
FromType, ImplicitParamType);
return ICS;
}
if (FromTypeCanon.hasAddressSpace()) {
Qualifiers QualsImplicitParamType = ImplicitParamType.getQualifiers();
Qualifiers QualsFromType = FromTypeCanon.getQualifiers();
if (!QualsImplicitParamType.isAddressSpaceSupersetOf(QualsFromType)) {
ICS.setBad(BadConversionSequence::bad_qualifiers,
FromType, ImplicitParamType);
return ICS;
}
}
QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
ImplicitConversionKind SecondKind;
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
SecondKind = ICK_Identity;
} else if (S.IsDerivedFrom(Loc, FromType, ClassType))
SecondKind = ICK_Derived_To_Base;
else {
ICS.setBad(BadConversionSequence::unrelated_class,
FromType, ImplicitParamType);
return ICS;
}
switch (Method->getRefQualifier()) {
case RQ_None:
break;
case RQ_LValue:
if (!FromClassification.isLValue() && !Quals.hasOnlyConst()) {
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType,
ImplicitParamType);
return ICS;
}
break;
case RQ_RValue:
if (!FromClassification.isRValue()) {
ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType,
ImplicitParamType);
return ICS;
}
break;
}
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.Second = SecondKind;
ICS.Standard.setFromType(FromType);
ICS.Standard.setAllToTypes(ImplicitParamType);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue;
ICS.Standard.BindsToFunctionLvalue = false;
ICS.Standard.BindsToRvalue = FromClassification.isRValue();
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier
= (Method->getRefQualifier() == RQ_None);
return ICS;
}
ExprResult
Sema::PerformObjectArgumentInitialization(Expr *From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType =
Method->getThisType()->castAs<PointerType>()->getPointeeType();
Expr::Classification FromClassification;
if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
FromRecordType = PT->getPointeeType();
DestType = Method->getThisType();
FromClassification = Expr::Classification::makeSimpleLValue();
} else {
FromRecordType = From->getType();
DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context);
if (From->isPRValue()) {
From = CreateMaterializeTemporaryExpr(FromRecordType, From,
Method->getRefQualifier() !=
RefQualifierKind::RQ_RValue);
}
}
ImplicitConversionSequence ICS = TryObjectArgumentInitialization(
*this, From->getBeginLoc(), From->getType(), FromClassification, Method,
Method->getParent());
if (ICS.isBad()) {
switch (ICS.Bad.Kind) {
case BadConversionSequence::bad_qualifiers: {
Qualifiers FromQs = FromRecordType.getQualifiers();
Qualifiers ToQs = DestType.getQualifiers();
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
if (CVR) {
Diag(From->getBeginLoc(), diag::err_member_function_call_bad_cvr)
<< Method->getDeclName() << FromRecordType << (CVR - 1)
<< From->getSourceRange();
Diag(Method->getLocation(), diag::note_previous_decl)
<< Method->getDeclName();
return ExprError();
}
break;
}
case BadConversionSequence::lvalue_ref_to_rvalue:
case BadConversionSequence::rvalue_ref_to_lvalue: {
bool IsRValueQualified =
Method->getRefQualifier() == RefQualifierKind::RQ_RValue;
Diag(From->getBeginLoc(), diag::err_member_function_call_bad_ref)
<< Method->getDeclName() << FromClassification.isRValue()
<< IsRValueQualified;
Diag(Method->getLocation(), diag::note_previous_decl)
<< Method->getDeclName();
return ExprError();
}
case BadConversionSequence::no_conversion:
case BadConversionSequence::unrelated_class:
break;
case BadConversionSequence::too_few_initializers:
case BadConversionSequence::too_many_initializers:
llvm_unreachable("Lists are not objects");
}
return Diag(From->getBeginLoc(), diag::err_member_function_call_bad_type)
<< ImplicitParamRecordType << FromRecordType
<< From->getSourceRange();
}
if (ICS.Standard.Second == ICK_Derived_To_Base) {
ExprResult FromRes =
PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
if (FromRes.isInvalid())
return ExprError();
From = FromRes.get();
}
if (!Context.hasSameType(From->getType(), DestType)) {
CastKind CK;
QualType PteeTy = DestType->getPointeeType();
LangAS DestAS =
PteeTy.isNull() ? DestType.getAddressSpace() : PteeTy.getAddressSpace();
if (FromRecordType.getAddressSpace() != DestAS)
CK = CK_AddressSpaceConversion;
else
CK = CK_NoOp;
From = ImpCastExprToType(From, DestType, CK, From->getValueKind()).get();
}
return From;
}
static ImplicitConversionSequence
TryContextuallyConvertToBool(Sema &S, Expr *From) {
if (From->getType()->isNullPtrType())
return ImplicitConversionSequence::getNullptrToBool(From->getType(),
S.Context.BoolTy,
From->isGLValue());
return TryImplicitConversion(S, From, S.Context.BoolTy,
false,
AllowedExplicit::Conversions,
false,
false,
false,
false);
}
ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
if (checkPlaceholderForOverload(*this, From))
return ExprError();
ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
return Diag(From->getBeginLoc(), diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
return ExprError();
}
static bool CheckConvertedConstantConversions(Sema &S,
StandardConversionSequence &SCS) {
switch (SCS.Second) {
case ICK_Identity:
case ICK_Integral_Promotion:
case ICK_Integral_Conversion: case ICK_Zero_Queue_Conversion:
return true;
case ICK_Boolean_Conversion:
return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
SCS.getToType(2)->isBooleanType();
case ICK_Pointer_Conversion:
case ICK_Pointer_Member:
return SCS.getFromType()->isNullPtrType();
case ICK_Floating_Promotion:
case ICK_Complex_Promotion:
case ICK_Floating_Conversion:
case ICK_Complex_Conversion:
case ICK_Floating_Integral:
case ICK_Compatible_Conversion:
case ICK_Derived_To_Base:
case ICK_Vector_Conversion:
case ICK_SVE_Vector_Conversion:
case ICK_Vector_Splat:
case ICK_Complex_Real:
case ICK_Block_Pointer_Conversion:
case ICK_TransparentUnionConversion:
case ICK_Writeback_Conversion:
case ICK_Zero_Event_Conversion:
case ICK_C_Only_Conversion:
case ICK_Incompatible_Pointer_Conversion:
return false;
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
llvm_unreachable("found a first conversion kind in Second");
case ICK_Function_Conversion:
case ICK_Qualification:
llvm_unreachable("found a third conversion kind in Second");
case ICK_Num_Conversion_Kinds:
break;
}
llvm_unreachable("unknown conversion kind");
}
static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
QualType T, APValue &Value,
Sema::CCEKind CCE,
bool RequireInt,
NamedDecl *Dest) {
assert(S.getLangOpts().CPlusPlus11 &&
"converted constant expression outside C++11");
if (checkPlaceholderForOverload(S, From))
return ExprError();
ImplicitConversionSequence ICS =
(CCE == Sema::CCEK_ExplicitBool || CCE == Sema::CCEK_Noexcept)
? TryContextuallyConvertToBool(S, From)
: TryCopyInitialization(S, From, T,
false,
false,
false,
false);
StandardConversionSequence *SCS = nullptr;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
SCS = &ICS.Standard;
break;
case ImplicitConversionSequence::UserDefinedConversion:
if (T->isRecordType())
SCS = &ICS.UserDefined.Before;
else
SCS = &ICS.UserDefined.After;
break;
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::BadConversion:
if (!S.DiagnoseMultipleUserDefinedConversion(From, T))
return S.Diag(From->getBeginLoc(),
diag::err_typecheck_converted_constant_expression)
<< From->getType() << From->getSourceRange() << T;
return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
llvm_unreachable("ellipsis conversion in converted constant expression");
}
if (!CheckConvertedConstantConversions(S, *SCS)) {
return S.Diag(From->getBeginLoc(),
diag::err_typecheck_converted_constant_expression_disallowed)
<< From->getType() << From->getSourceRange() << T;
}
if (SCS->ReferenceBinding && !SCS->DirectBinding) {
return S.Diag(From->getBeginLoc(),
diag::err_typecheck_converted_constant_expression_indirect)
<< From->getType() << From->getSourceRange() << T;
}
ExprResult Result;
if (T->isRecordType()) {
assert(CCE == Sema::CCEK_TemplateArg &&
"unexpected class type converted constant expr");
Result = S.PerformCopyInitialization(
InitializedEntity::InitializeTemplateParameter(
T, cast<NonTypeTemplateParmDecl>(Dest)),
SourceLocation(), From);
} else {
Result = S.PerformImplicitConversion(From, T, ICS, Sema::AA_Converting);
}
if (Result.isInvalid())
return Result;
Result =
S.ActOnFinishFullExpr(Result.get(), From->getExprLoc(),
false, true);
if (Result.isInvalid())
return Result;
bool ReturnPreNarrowingValue = false;
APValue PreNarrowingValue;
QualType PreNarrowingType;
switch (SCS->getNarrowingKind(S.Context, Result.get(), PreNarrowingValue,
PreNarrowingType)) {
case NK_Dependent_Narrowing:
case NK_Variable_Narrowing:
case NK_Not_Narrowing:
break;
case NK_Constant_Narrowing:
if (CCE == Sema::CCEK_ArrayBound &&
PreNarrowingType->isIntegralOrEnumerationType() &&
PreNarrowingValue.isInt()) {
ReturnPreNarrowingValue = true;
break;
}
S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
<< CCE << 1
<< PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
S.Diag(From->getBeginLoc(), diag::ext_cce_narrowing)
<< CCE << 0 << From->getType() << T;
break;
}
if (Result.get()->isValueDependent()) {
Value = APValue();
return Result;
}
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
ConstantExprKind Kind;
if (CCE == Sema::CCEK_TemplateArg && T->isRecordType())
Kind = ConstantExprKind::ClassTemplateArgument;
else if (CCE == Sema::CCEK_TemplateArg)
Kind = ConstantExprKind::NonClassTemplateArgument;
else
Kind = ConstantExprKind::Normal;
if (!Result.get()->EvaluateAsConstantExpr(Eval, S.Context, Kind) ||
(RequireInt && !Eval.Val.isInt())) {
Result = ExprError();
} else {
Value = Eval.Val;
if (Notes.empty()) {
Expr *E = ConstantExpr::Create(S.Context, Result.get(), Value);
if (ReturnPreNarrowingValue)
Value = std::move(PreNarrowingValue);
return E;
}
}
if (Notes.size() == 1 &&
Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr) {
S.Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
} else if (!Notes.empty() && Notes[0].second.getDiagID() ==
diag::note_constexpr_invalid_template_arg) {
Notes[0].second.setDiagID(diag::err_constexpr_invalid_template_arg);
for (unsigned I = 0; I < Notes.size(); ++I)
S.Diag(Notes[I].first, Notes[I].second);
} else {
S.Diag(From->getBeginLoc(), diag::err_expr_not_cce)
<< CCE << From->getSourceRange();
for (unsigned I = 0; I < Notes.size(); ++I)
S.Diag(Notes[I].first, Notes[I].second);
}
return ExprError();
}
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
APValue &Value, CCEKind CCE,
NamedDecl *Dest) {
return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false,
Dest);
}
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value,
CCEKind CCE) {
assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
APValue V;
auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true,
nullptr);
if (!R.isInvalid() && !R.get()->isValueDependent())
Value = V.getInt();
return R;
}
static void dropPointerConversion(StandardConversionSequence &SCS) {
if (SCS.Second == ICK_Pointer_Conversion) {
SCS.Second = ICK_Identity;
SCS.Third = ICK_Identity;
SCS.ToTypePtrs[2] = SCS.ToTypePtrs[1] = SCS.ToTypePtrs[0];
}
}
static ImplicitConversionSequence
TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
QualType Ty = S.Context.getObjCIdType();
ImplicitConversionSequence ICS
= TryImplicitConversion(S, From, Ty,
false,
AllowedExplicit::Conversions,
false,
false,
false,
true);
switch (ICS.getKind()) {
case ImplicitConversionSequence::BadConversion:
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::EllipsisConversion:
break;
case ImplicitConversionSequence::UserDefinedConversion:
dropPointerConversion(ICS.UserDefined.After);
break;
case ImplicitConversionSequence::StandardConversion:
dropPointerConversion(ICS.Standard);
break;
}
return ICS;
}
ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
if (checkPlaceholderForOverload(*this, From))
return ExprError();
QualType Ty = Context.getObjCIdType();
ImplicitConversionSequence ICS =
TryContextuallyConvertToObjCPointer(*this, From);
if (!ICS.isBad())
return PerformImplicitConversion(From, Ty, ICS, AA_Converting);
return ExprResult();
}
bool Sema::ICEConvertDiagnoser::match(QualType T) {
return AllowScopedEnumerations ? T->isIntegralOrEnumerationType()
: T->isIntegralOrUnscopedEnumerationType();
}
static ExprResult
diagnoseAmbiguousConversion(Sema &SemaRef, SourceLocation Loc, Expr *From,
Sema::ContextualImplicitConverter &Converter,
QualType T, UnresolvedSetImpl &ViableConversions) {
if (Converter.Suppress)
return ExprError();
Converter.diagnoseAmbiguous(SemaRef, Loc, T) << From->getSourceRange();
for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
CXXConversionDecl *Conv =
cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
QualType ConvTy = Conv->getConversionType().getNonReferenceType();
Converter.noteAmbiguous(SemaRef, Conv, ConvTy);
}
return From;
}
static bool
diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
Sema::ContextualImplicitConverter &Converter,
QualType T, bool HadMultipleCandidates,
UnresolvedSetImpl &ExplicitConversions) {
if (ExplicitConversions.size() == 1 && !Converter.Suppress) {
DeclAccessPair Found = ExplicitConversions[0];
CXXConversionDecl *Conversion =
cast<CXXConversionDecl>(Found->getUnderlyingDecl());
QualType ConvTy = Conversion->getConversionType().getNonReferenceType();
std::string TypeStr;
ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy());
Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy)
<< FixItHint::CreateInsertion(From->getBeginLoc(),
"static_cast<" + TypeStr + ">(")
<< FixItHint::CreateInsertion(
SemaRef.getLocForEndOfToken(From->getEndLoc()), ")");
Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
if (SemaRef.isSFINAEContext())
return true;
SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, nullptr, Found);
ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
HadMultipleCandidates);
if (Result.isInvalid())
return true;
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
CK_UserDefinedConversion, Result.get(),
nullptr, Result.get()->getValueKind(),
SemaRef.CurFPFeatureOverrides());
}
return false;
}
static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
Sema::ContextualImplicitConverter &Converter,
QualType T, bool HadMultipleCandidates,
DeclAccessPair &Found) {
CXXConversionDecl *Conversion =
cast<CXXConversionDecl>(Found->getUnderlyingDecl());
SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, nullptr, Found);
QualType ToType = Conversion->getConversionType().getNonReferenceType();
if (!Converter.SuppressConversion) {
if (SemaRef.isSFINAEContext())
return true;
Converter.diagnoseConversion(SemaRef, Loc, T, ToType)
<< From->getSourceRange();
}
ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
HadMultipleCandidates);
if (Result.isInvalid())
return true;
From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
CK_UserDefinedConversion, Result.get(),
nullptr, Result.get()->getValueKind(),
SemaRef.CurFPFeatureOverrides());
return false;
}
static ExprResult finishContextualImplicitConversion(
Sema &SemaRef, SourceLocation Loc, Expr *From,
Sema::ContextualImplicitConverter &Converter) {
if (!Converter.match(From->getType()) && !Converter.Suppress)
Converter.diagnoseNoMatch(SemaRef, Loc, From->getType())
<< From->getSourceRange();
return SemaRef.DefaultLvalueConversion(From);
}
static void
collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType,
UnresolvedSetImpl &ViableConversions,
OverloadCandidateSet &CandidateSet) {
for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
DeclAccessPair FoundDecl = ViableConversions[I];
NamedDecl *D = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
CXXConversionDecl *Conv;
FunctionTemplateDecl *ConvTemplate;
if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D)))
Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
Conv = cast<CXXConversionDecl>(D);
if (ConvTemplate)
SemaRef.AddTemplateConversionCandidate(
ConvTemplate, FoundDecl, ActingContext, From, ToType, CandidateSet,
false, true);
else
SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From,
ToType, CandidateSet,
false,
true);
}
}
ExprResult Sema::PerformContextualImplicitConversion(
SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) {
if (From->isTypeDependent())
return From;
if (From->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(From);
if (result.isInvalid())
return result;
From = result.get();
}
QualType T = From->getType();
if (Converter.match(T))
return DefaultLvalueConversion(From);
const RecordType *RecordTy = T->getAs<RecordType>();
if (!RecordTy || !getLangOpts().CPlusPlus) {
if (!Converter.Suppress)
Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange();
return From;
}
struct TypeDiagnoserPartialDiag : TypeDiagnoser {
ContextualImplicitConverter &Converter;
Expr *From;
TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
: Converter(Converter), From(From) {}
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
} IncompleteDiagnoser(Converter, From);
if (Converter.Suppress ? !isCompleteType(Loc, T)
: RequireCompleteType(Loc, T, IncompleteDiagnoser))
return From;
UnresolvedSet<4>
ViableConversions; UnresolvedSet<4> ExplicitConversions;
const auto &Conversions =
cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
bool HadMultipleCandidates =
(std::distance(Conversions.begin(), Conversions.end()) > 1);
QualType ToType;
bool HasUniqueTargetType = true;
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
CXXConversionDecl *Conversion;
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
if (ConvTemplate) {
if (getLangOpts().CPlusPlus14)
Conversion = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
continue; } else
Conversion = cast<CXXConversionDecl>(D);
assert((!ConvTemplate || getLangOpts().CPlusPlus14) &&
"Conversion operator templates are considered potentially "
"viable in C++1y");
QualType CurToType = Conversion->getConversionType().getNonReferenceType();
if (Converter.match(CurToType) || ConvTemplate) {
if (Conversion->isExplicit()) {
if (!ConvTemplate)
ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
} else {
if (!ConvTemplate && getLangOpts().CPlusPlus14) {
if (ToType.isNull())
ToType = CurToType.getUnqualifiedType();
else if (HasUniqueTargetType &&
(CurToType.getUnqualifiedType() != ToType))
HasUniqueTargetType = false;
}
ViableConversions.addDecl(I.getDecl(), I.getAccess());
}
}
}
if (getLangOpts().CPlusPlus14) {
if (ToType.isNull()) {
if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
HadMultipleCandidates,
ExplicitConversions))
return ExprError();
return finishContextualImplicitConversion(*this, Loc, From, Converter);
}
if (!HasUniqueTargetType)
return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
ViableConversions);
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
collectViableConversionCandidates(*this, From, ToType, ViableConversions,
CandidateSet);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, Loc, Best)) {
case OR_Success: {
DeclAccessPair Found =
DeclAccessPair::make(Best->Function, Best->FoundDecl.getAccess());
if (recordConversion(*this, Loc, From, Converter, T,
HadMultipleCandidates, Found))
return ExprError();
break;
}
case OR_Ambiguous:
return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
ViableConversions);
case OR_No_Viable_Function:
if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
HadMultipleCandidates,
ExplicitConversions))
return ExprError();
LLVM_FALLTHROUGH;
case OR_Deleted:
break;
}
} else {
switch (ViableConversions.size()) {
case 0: {
if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
HadMultipleCandidates,
ExplicitConversions))
return ExprError();
break;
}
case 1: {
DeclAccessPair Found = ViableConversions[0];
if (recordConversion(*this, Loc, From, Converter, T,
HadMultipleCandidates, Found))
return ExprError();
break;
}
default:
return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
ViableConversions);
}
}
return finishContextualImplicitConversion(*this, Loc, From, Converter);
}
static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context,
FunctionDecl *Fn,
ArrayRef<Expr *> Args) {
QualType T1 = Args[0]->getType();
QualType T2 = Args.size() > 1 ? Args[1]->getType() : QualType();
if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType()))
return true;
if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType()))
return true;
const auto *Proto = Fn->getType()->castAs<FunctionProtoType>();
if (Proto->getNumParams() < 1)
return false;
if (T1->isEnumeralType()) {
QualType ArgType = Proto->getParamType(0).getNonReferenceType();
if (Context.hasSameUnqualifiedType(T1, ArgType))
return true;
}
if (Proto->getNumParams() < 2)
return false;
if (!T2.isNull() && T2->isEnumeralType()) {
QualType ArgType = Proto->getParamType(1).getNonReferenceType();
if (Context.hasSameUnqualifiedType(T2, ArgType))
return true;
}
return false;
}
void Sema::AddOverloadCandidate(
FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
OverloadCandidateParamOrder PO) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
assert(Proto && "Functions without a prototype cannot be overloaded");
assert(!Function->getDescribedFunctionTemplate() &&
"Use AddTemplateOverloadCandidate for function templates");
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
if (!isa<CXXConstructorDecl>(Method)) {
AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
Expr::Classification::makeSimpleLValue(), Args,
CandidateSet, SuppressUserConversions,
PartialOverloading, EarlyConversions, PO);
return;
}
}
if (!CandidateSet.isNewCandidate(Function, PO))
return;
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function);
if (Constructor && Constructor->isDefaulted() && Constructor->isDeleted() &&
Constructor->isMoveConstructor())
return;
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
if (CandidateSet.getKind() == OverloadCandidateSet::CSK_Operator &&
!IsAcceptableNonMemberOperatorCandidate(Context, Function, Args))
return;
OverloadCandidate &Candidate =
CandidateSet.addCandidate(Args.size(), EarlyConversions);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Function;
Candidate.Viable = true;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Function, PO);
Candidate.IsSurrogate = false;
Candidate.IsADLCandidate = IsADLCandidate;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
if (!AllowExplicit && ExplicitSpecifier::getFromDecl(Function).isExplicit()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_explicit;
return;
}
if (auto *MF = Function->getOwningModule()) {
if (getLangOpts().CPlusPlusModules && !MF->isModuleMapModule() &&
!isModuleUnitOfCurrentTU(MF)) {
NamedDecl *ND = Function;
if (auto *SpecInfo = Function->getTemplateSpecializationInfo())
ND = SpecInfo->getTemplate();
if (ND->getFormalLinkage() == Linkage::InternalLinkage) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_module_mismatched;
return;
}
}
}
if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() &&
!Function->getAttr<TargetAttr>()->isDefaultVersion()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_non_default_multiversion_function;
return;
}
if (Constructor) {
QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
if (Args.size() == 1 && Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
IsDerivedFrom(Args[0]->getBeginLoc(), Args[0]->getType(),
ClassType))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_illegal_constructor;
return;
}
auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl.getDecl());
if (Shadow && Args.size() == 1 && Constructor->getNumParams() >= 1 &&
Constructor->getParamDecl(0)->getType()->isReferenceType()) {
QualType P = Constructor->getParamDecl(0)->getType()->getPointeeType();
QualType C = Context.getRecordType(Constructor->getParent());
QualType D = Context.getRecordType(Shadow->getParent());
SourceLocation Loc = Args.front()->getExprLoc();
if ((Context.hasSameUnqualifiedType(P, C) || IsDerivedFrom(Loc, P, C)) &&
(Context.hasSameUnqualifiedType(D, P) || IsDerivedFrom(Loc, D, P))) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_inhctor_slice;
return;
}
}
if (!Qualifiers::isAddressSpaceSupersetOf(
Constructor->getMethodQualifiers().getAddressSpace(),
CandidateSet.getDestAS())) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_object_addrspace_mismatch;
}
}
unsigned NumParams = Proto->getNumParams();
if (TooManyArguments(NumParams, Args.size(), PartialOverloading) &&
!Proto->isVariadic() &&
shouldEnforceArgLimit(PartialOverloading, Function)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
}
unsigned MinRequiredArgs = Function->getMinRequiredArguments();
if (Args.size() < MinRequiredArgs && !PartialOverloading) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
return;
}
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = getCurFunctionDecl(true))
if (!Caller->isImplicit() && !IsAllowedCUDACall(Caller, Function)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_target;
return;
}
if (Function->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckFunctionConstraints(Function, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
return;
}
}
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
unsigned ConvIdx =
PO == OverloadCandidateParamOrder::Reversed ? 1 - ArgIdx : ArgIdx;
if (Candidate.Conversions[ConvIdx].isInitialized()) {
} else if (ArgIdx < NumParams) {
QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ConvIdx] = TryCopyInitialization(
*this, Args[ArgIdx], ParamType, SuppressUserConversions,
true,
getLangOpts().ObjCAutoRefCount, AllowExplicitConversions);
if (Candidate.Conversions[ConvIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
} else {
Candidate.Conversions[ConvIdx].setEllipsis();
}
}
if (EnableIfAttr *FailedAttr =
CheckEnableIf(Function, CandidateSet.getLocation(), Args)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
}
ObjCMethodDecl *
Sema::SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance,
SmallVectorImpl<ObjCMethodDecl *> &Methods) {
if (Methods.size() <= 1)
return nullptr;
for (unsigned b = 0, e = Methods.size(); b < e; b++) {
bool Match = true;
ObjCMethodDecl *Method = Methods[b];
unsigned NumNamedArgs = Sel.getNumArgs();
if (Method->param_size() > NumNamedArgs)
NumNamedArgs = Method->param_size();
if (Args.size() < NumNamedArgs)
continue;
for (unsigned i = 0; i < NumNamedArgs; i++) {
if (Args[i]->isTypeDependent()) {
Match = false;
break;
}
ParmVarDecl *param = Method->parameters()[i];
Expr *argExpr = Args[i];
assert(argExpr && "SelectBestMethod(): missing expression");
if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
!param->hasAttr<CFConsumedAttr>())
argExpr = stripARCUnbridgedCast(argExpr);
if (param->getType() == Context.UnknownAnyTy) {
Match = false;
break;
}
ImplicitConversionSequence ConversionState
= TryCopyInitialization(*this, argExpr, param->getType(),
false,
true,
getLangOpts().ObjCAutoRefCount,
false);
if (ConversionState.isBad() ||
(ConversionState.isStandard() &&
ConversionState.Standard.Second ==
ICK_Incompatible_Pointer_Conversion)) {
Match = false;
break;
}
}
if (Match && Method->isVariadic()) {
for (unsigned i = NumNamedArgs, e = Args.size(); i < e; ++i) {
if (Args[i]->isTypeDependent()) {
Match = false;
break;
}
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
nullptr);
if (Arg.isInvalid()) {
Match = false;
break;
}
}
} else {
if (Args.size() != NumNamedArgs)
Match = false;
else if (Match && NumNamedArgs == 0 && Methods.size() > 1) {
for (unsigned b = 0, e = Methods.size(); b < e; b++) {
QualType ReturnT = Methods[b]->getReturnType();
if (ReturnT->isObjCIdType())
return Methods[b];
}
}
}
if (Match)
return Method;
}
return nullptr;
}
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) &&
"Shouldn't have `this` for ctors!");
assert(!Method->isStatic() && "Shouldn't have `this` for static methods!");
ExprResult R = S.PerformObjectArgumentInitialization(
ThisArg, nullptr, Method, Method);
if (R.isInvalid())
return false;
ConvertedThis = R.get();
} else {
if (auto *MD = dyn_cast<CXXMethodDecl>(Function)) {
(void)MD;
assert((MissingImplicitThis || MD->isStatic() ||
isa<CXXConstructorDecl>(MD)) &&
"Expected `this` for non-ctor instance methods");
}
ConvertedThis = nullptr;
}
unsigned ArgSizeNoVarargs = std::min(Function->param_size(), Args.size());
for (unsigned I = 0; I != ArgSizeNoVarargs; ++I) {
ExprResult R;
R = S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
S.Context, Function->getParamDecl(I)),
SourceLocation(), Args[I]);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
}
if (Trap.hasErrorOccurred())
return false;
if (!Function->isVariadic() && Args.size() < Function->getNumParams()) {
for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) {
ParmVarDecl *P = Function->getParamDecl(i);
if (!P->hasDefaultArg())
return false;
ExprResult R = S.BuildCXXDefaultArgExpr(CallLoc, Function, P);
if (R.isInvalid())
return false;
ConvertedArgs.push_back(R.get());
}
if (Trap.hasErrorOccurred())
return false;
}
return true;
}
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function,
SourceLocation CallLoc,
ArrayRef<Expr *> Args,
bool MissingImplicitThis) {
auto EnableIfAttrs = Function->specific_attrs<EnableIfAttr>();
if (EnableIfAttrs.begin() == EnableIfAttrs.end())
return nullptr;
SFINAETrap Trap(*this);
SmallVector<Expr *, 16> ConvertedArgs;
Expr *DiscardedThis;
if (!convertArgsForAvailabilityChecks(
*this, Function, nullptr, CallLoc, Args, Trap,
true, DiscardedThis, ConvertedArgs))
return *EnableIfAttrs.begin();
for (auto *EIA : EnableIfAttrs) {
APValue Result;
if (EIA->getCond()->isValueDependent() ||
!EIA->getCond()->EvaluateWithSubstitution(
Result, Context, Function, llvm::makeArrayRef(ConvertedArgs)))
return EIA;
if (!Result.isInt() || !Result.getInt().getBoolValue())
return EIA;
}
return nullptr;
}
template <typename CheckFn>
static bool diagnoseDiagnoseIfAttrsWith(Sema &S, const NamedDecl *ND,
bool ArgDependent, SourceLocation Loc,
CheckFn &&IsSuccessful) {
SmallVector<const DiagnoseIfAttr *, 8> Attrs;
for (const auto *DIA : ND->specific_attrs<DiagnoseIfAttr>()) {
if (ArgDependent == DIA->getArgDependent())
Attrs.push_back(DIA);
}
if (Attrs.empty())
return false;
auto WarningBegin = std::stable_partition(
Attrs.begin(), Attrs.end(),
[](const DiagnoseIfAttr *DIA) { return DIA->isError(); });
auto ErrAttr = llvm::find_if(llvm::make_range(Attrs.begin(), WarningBegin),
IsSuccessful);
if (ErrAttr != WarningBegin) {
const DiagnoseIfAttr *DIA = *ErrAttr;
S.Diag(Loc, diag::err_diagnose_if_succeeded) << DIA->getMessage();
S.Diag(DIA->getLocation(), diag::note_from_diagnose_if)
<< DIA->getParent() << DIA->getCond()->getSourceRange();
return true;
}
for (const auto *DIA : llvm::make_range(WarningBegin, Attrs.end()))
if (IsSuccessful(DIA)) {
S.Diag(Loc, diag::warn_diagnose_if_succeeded) << DIA->getMessage();
S.Diag(DIA->getLocation(), diag::note_from_diagnose_if)
<< DIA->getParent() << DIA->getCond()->getSourceRange();
}
return false;
}
bool Sema::diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function,
const Expr *ThisArg,
ArrayRef<const Expr *> Args,
SourceLocation Loc) {
return diagnoseDiagnoseIfAttrsWith(
*this, Function, true, Loc,
[&](const DiagnoseIfAttr *DIA) {
APValue Result;
if (!DIA->getCond()->EvaluateWithSubstitution(
Result, Context, cast<FunctionDecl>(DIA->getParent()), Args, ThisArg))
return false;
return Result.isInt() && Result.getInt().getBoolValue();
});
}
bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
SourceLocation Loc) {
return diagnoseDiagnoseIfAttrsWith(
*this, ND, false, Loc,
[&](const DiagnoseIfAttr *DIA) {
bool Result;
return DIA->getCond()->EvaluateAsBooleanCondition(Result, Context) &&
Result;
});
}
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
bool PartialOverloading,
bool FirstArgumentIsBase) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
ArrayRef<Expr *> FunctionArgs = Args;
FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
FunctionDecl *FD =
FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D);
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
QualType ObjectType;
Expr::Classification ObjectClassification;
if (Args.size() > 0) {
if (Expr *E = Args[0]) {
ObjectType = E->getType();
if (!ObjectType.isNull() && ObjectType->isPointerType())
ObjectClassification = Expr::Classification::makeSimpleLValue();
else
ObjectClassification = E->Classify(Context);
} FunctionArgs = Args.slice(1);
}
if (FunTmpl) {
AddMethodTemplateCandidate(
FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
ExplicitTemplateArgs, ObjectType, ObjectClassification,
FunctionArgs, CandidateSet, SuppressUserConversions,
PartialOverloading);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
ObjectClassification, FunctionArgs, CandidateSet,
SuppressUserConversions, PartialOverloading);
}
} else {
if (Args.size() > 0 &&
(!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) &&
!isa<CXXConstructorDecl>(FD)))) {
assert(cast<CXXMethodDecl>(FD)->isStatic());
FunctionArgs = Args.slice(1);
}
if (FunTmpl) {
AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
ExplicitTemplateArgs, FunctionArgs,
CandidateSet, SuppressUserConversions,
PartialOverloading);
} else {
AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet,
SuppressUserConversions, PartialOverloading);
}
}
}
}
void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
OverloadCandidateParamOrder PO) {
NamedDecl *Decl = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext());
if (isa<UsingShadowDecl>(Decl))
Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl();
if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
nullptr, ObjectType,
ObjectClassification, Args, CandidateSet,
SuppressUserConversions, false, PO);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
ObjectType, ObjectClassification, Args, CandidateSet,
SuppressUserConversions, false, None, PO);
}
}
void
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
ConversionSequenceList EarlyConversions,
OverloadCandidateParamOrder PO) {
const FunctionProtoType *Proto
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
assert(Proto && "Methods without a prototype cannot be overloaded");
assert(!isa<CXXConstructorDecl>(Method) &&
"Use AddOverloadCandidate for constructors");
if (!CandidateSet.isNewCandidate(Method, PO))
return;
if (Method->isDefaulted() && Method->isDeleted() &&
Method->isMoveAssignmentOperator())
return;
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
OverloadCandidate &Candidate =
CandidateSet.addCandidate(Args.size() + 1, EarlyConversions);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Method;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Method, PO);
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
unsigned NumParams = Proto->getNumParams();
if (TooManyArguments(NumParams, Args.size(), PartialOverloading) &&
!Proto->isVariadic() &&
shouldEnforceArgLimit(PartialOverloading, Method)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
}
unsigned MinRequiredArgs = Method->getMinRequiredArguments();
if (Args.size() < MinRequiredArgs && !PartialOverloading) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
return;
}
Candidate.Viable = true;
if (Method->isStatic() || ObjectType.isNull())
Candidate.IgnoreObjectArgument = true;
else {
unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0;
Candidate.Conversions[ConvIdx] = TryObjectArgumentInitialization(
*this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
Method, ActingContext);
if (Candidate.Conversions[ConvIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
}
if (getLangOpts().CUDA)
if (const FunctionDecl *Caller = getCurFunctionDecl(true))
if (!IsAllowedCUDACall(Caller, Method)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_target;
return;
}
if (Method->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckFunctionConstraints(Method, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
return;
}
}
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
unsigned ConvIdx =
PO == OverloadCandidateParamOrder::Reversed ? 0 : (ArgIdx + 1);
if (Candidate.Conversions[ConvIdx].isInitialized()) {
} else if (ArgIdx < NumParams) {
QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ConvIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
true,
getLangOpts().ObjCAutoRefCount);
if (Candidate.Conversions[ConvIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
} else {
Candidate.Conversions[ConvIdx].setEllipsis();
}
}
if (EnableIfAttr *FailedAttr =
CheckEnableIf(Method, CandidateSet.getLocation(), Args, true)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
if (Method->isMultiVersion() && Method->hasAttr<TargetAttr>() &&
!Method->getAttr<TargetAttr>()->isDefaultVersion()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_non_default_multiversion_function;
}
}
void Sema::AddMethodTemplateCandidate(
FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType,
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, OverloadCandidateParamOrder PO) {
if (!CandidateSet.isNewCandidate(MethodTmpl, PO))
return;
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = nullptr;
ConversionSequenceList Conversions;
if (TemplateDeductionResult Result = DeduceTemplateArguments(
MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, [&](ArrayRef<QualType> ParamTypes) {
return CheckNonDependentConversions(
MethodTmpl, ParamTypes, Args, CandidateSet, Conversions,
SuppressUserConversions, ActingContext, ObjectType,
ObjectClassification, PO);
})) {
OverloadCandidate &Candidate =
CandidateSet.addCandidate(Conversions.size(), Conversions);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = MethodTmpl->getTemplatedDecl();
Candidate.Viable = false;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Candidate.Function, PO);
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument =
cast<CXXMethodDecl>(Candidate.Function)->isStatic() ||
ObjectType.isNull();
Candidate.ExplicitCallArguments = Args.size();
if (Result == TDK_NonDependentConversionFailure)
Candidate.FailureKind = ovl_fail_bad_conversion;
else {
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
}
return;
}
assert(Specialization && "Missing member function template specialization?");
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, ObjectClassification, Args,
CandidateSet, SuppressUserConversions, PartialOverloading,
Conversions, PO);
}
static bool isNonDependentlyExplicit(FunctionTemplateDecl *FTD) {
return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).isExplicit();
}
void Sema::AddTemplateOverloadCandidate(
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
bool PartialOverloading, bool AllowExplicit, ADLCallKind IsADLCandidate,
OverloadCandidateParamOrder PO) {
if (!CandidateSet.isNewCandidate(FunctionTemplate, PO))
return;
if (!AllowExplicit && isNonDependentlyExplicit(FunctionTemplate)) {
OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_explicit;
return;
}
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = nullptr;
ConversionSequenceList Conversions;
if (TemplateDeductionResult Result = DeduceTemplateArguments(
FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, [&](ArrayRef<QualType> ParamTypes) {
return CheckNonDependentConversions(
FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions,
SuppressUserConversions, nullptr, QualType(), {}, PO);
})) {
OverloadCandidate &Candidate =
CandidateSet.addCandidate(Conversions.size(), Conversions);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.RewriteKind =
CandidateSet.getRewriteInfo().getRewriteKind(Candidate.Function, PO);
Candidate.IsSurrogate = false;
Candidate.IsADLCandidate = IsADLCandidate;
Candidate.IgnoreObjectArgument =
isa<CXXMethodDecl>(Candidate.Function) &&
!isa<CXXConstructorDecl>(Candidate.Function);
Candidate.ExplicitCallArguments = Args.size();
if (Result == TDK_NonDependentConversionFailure)
Candidate.FailureKind = ovl_fail_bad_conversion;
else {
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
}
return;
}
assert(Specialization && "Missing function template specialization?");
AddOverloadCandidate(
Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
PartialOverloading, AllowExplicit,
false, IsADLCandidate, Conversions, PO);
}
bool Sema::CheckNonDependentConversions(
FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes,
ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet,
ConversionSequenceList &Conversions, bool SuppressUserConversions,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification, OverloadCandidateParamOrder PO) {
const bool AllowExplicit = false;
auto *FD = FunctionTemplate->getTemplatedDecl();
auto *Method = dyn_cast<CXXMethodDecl>(FD);
bool HasThisConversion = Method && !isa<CXXConstructorDecl>(Method);
unsigned ThisConversions = HasThisConversion ? 1 : 0;
Conversions =
CandidateSet.allocateConversionSequences(ThisConversions + Args.size());
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
if (HasThisConversion && !cast<CXXMethodDecl>(FD)->isStatic() &&
!ObjectType.isNull()) {
unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed ? 1 : 0;
Conversions[ConvIdx] = TryObjectArgumentInitialization(
*this, CandidateSet.getLocation(), ObjectType, ObjectClassification,
Method, ActingContext);
if (Conversions[ConvIdx].isBad())
return true;
}
for (unsigned I = 0, N = std::min(ParamTypes.size(), Args.size()); I != N;
++I) {
QualType ParamType = ParamTypes[I];
if (!ParamType->isDependentType()) {
unsigned ConvIdx = PO == OverloadCandidateParamOrder::Reversed
? 0
: (ThisConversions + I);
Conversions[ConvIdx]
= TryCopyInitialization(*this, Args[I], ParamType,
SuppressUserConversions,
true,
getLangOpts().ObjCAutoRefCount,
AllowExplicit);
if (Conversions[ConvIdx].isBad())
return true;
}
}
return false;
}
static bool isAllowableExplicitConversion(Sema &S,
QualType ConvType, QualType ToType,
bool AllowObjCPointerConversion) {
QualType ToNonRefType = ToType.getNonReferenceType();
if (S.Context.hasSameUnqualifiedType(ConvType, ToNonRefType))
return true;
bool ObjCLifetimeConversion;
if (S.IsQualificationConversion(ConvType, ToNonRefType, false,
ObjCLifetimeConversion))
return true;
if (!AllowObjCPointerConversion)
return false;
bool IncompatibleObjC = false;
QualType ConvertedType;
return S.isObjCPointerConversion(ConvType, ToNonRefType, ConvertedType,
IncompatibleObjC);
}
void Sema::AddConversionCandidate(
CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
bool AllowExplicit, bool AllowResultConversion) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
if (!CandidateSet.isNewCandidate(Conversion))
return;
if (getLangOpts().CPlusPlus14 && ConvType->isUndeducedType()) {
if (DeduceReturnType(Conversion, From->getExprLoc()))
return;
ConvType = Conversion->getConversionType().getNonReferenceType();
}
if (!AllowResultConversion &&
!Context.hasSameUnqualifiedType(Conversion->getConversionType(), ToType))
return;
if (Conversion->isExplicit() &&
!isAllowableExplicitConversion(*this, ConvType, ToType,
AllowObjCConversionOnExplicit))
return;
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
OverloadCandidate &Candidate = CandidateSet.addCandidate(1);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Conversion;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(ConvType);
Candidate.FinalConversion.setAllToTypes(ToType);
Candidate.Viable = true;
Candidate.ExplicitCallArguments = 1;
if (!AllowExplicit && Conversion->isExplicit()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_explicit;
return;
}
QualType ImplicitParamType = From->getType();
if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
ImplicitParamType = FromPtrType->getPointeeType();
CXXRecordDecl *ConversionContext
= cast<CXXRecordDecl>(ImplicitParamType->castAs<RecordType>()->getDecl());
Candidate.Conversions[0] = TryObjectArgumentInitialization(
*this, CandidateSet.getLocation(), From->getType(),
From->Classify(Context), Conversion, ConversionContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
if (Conversion->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (CheckFunctionConstraints(Conversion, Satisfaction) ||
!Satisfaction.IsSatisfied) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_constraints_not_satisfied;
return;
}
}
QualType FromCanon
= Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
if (FromCanon == ToCanon ||
IsDerivedFrom(CandidateSet.getLocation(), FromCanon, ToCanon)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_trivial_conversion;
return;
}
DeclRefExpr ConversionRef(Context, Conversion, false, Conversion->getType(),
VK_LValue, From->getBeginLoc());
ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
Context.getPointerType(Conversion->getType()),
CK_FunctionToPointerDecay, &ConversionRef,
VK_PRValue, FPOptionsOverride());
QualType ConversionType = Conversion->getConversionType();
if (!isCompleteType(From->getBeginLoc(), ConversionType)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
}
ExprValueKind VK = Expr::getValueKindForType(ConversionType);
QualType CallResultType = ConversionType.getNonLValueExprType(Context);
alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)];
CallExpr *TheTemporaryCall = CallExpr::CreateTemporary(
Buffer, &ConversionFn, CallResultType, VK, From->getBeginLoc());
ImplicitConversionSequence ICS =
TryCopyInitialization(*this, TheTemporaryCall, ToType,
true,
false,
false);
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
Candidate.FinalConversion = ICS.Standard;
if (Conversion->getPrimaryTemplate() &&
GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_final_conversion_not_exact;
return;
}
if (ToType->isRValueReferenceType() &&
ICS.Standard.First == ICK_Lvalue_To_Rvalue) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
}
break;
case ImplicitConversionSequence::BadConversion:
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
default:
llvm_unreachable(
"Can only end up with a standard conversion sequence or failure");
}
if (EnableIfAttr *FailedAttr =
CheckEnableIf(Conversion, CandidateSet.getLocation(), None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
if (Conversion->isMultiVersion() && Conversion->hasAttr<TargetAttr>() &&
!Conversion->getAttr<TargetAttr>()->isDefaultVersion()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_non_default_multiversion_function;
}
}
void Sema::AddTemplateConversionCandidate(
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingDC, Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
bool AllowExplicit, bool AllowResultConversion) {
assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
"Only conversion function templates permitted here");
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
if (!AllowExplicit && isNonDependentlyExplicit(FunctionTemplate)) {
OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_explicit;
return;
}
TemplateDeductionInfo Info(CandidateSet.getLocation());
CXXConversionDecl *Specialization = nullptr;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ToType,
Specialization, Info)) {
OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = 1;
Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
return;
}
assert(Specialization && "Missing function template specialization?");
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
CandidateSet, AllowObjCConversionOnExplicit,
AllowExplicit, AllowResultConversion);
}
void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
Expr *Object,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet) {
if (!CandidateSet.isNewCandidate(Conversion))
return;
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = nullptr;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
ImplicitConversionSequence ObjectInit = TryObjectArgumentInitialization(
*this, CandidateSet.getLocation(), Object->getType(),
Object->Classify(Context), Conversion, ActingContext);
if (ObjectInit.isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
Candidate.Conversions[0] = ObjectInit;
return;
}
Candidate.Conversions[0].setUserDefined();
Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
Candidate.Conversions[0].UserDefined.HadMultipleCandidates = false;
Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
Candidate.Conversions[0].UserDefined.FoundConversionFunction = FoundDecl;
Candidate.Conversions[0].UserDefined.After
= Candidate.Conversions[0].UserDefined.Before;
Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion();
unsigned NumParams = Proto->getNumParams();
if (Args.size() > NumParams && !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
}
if (Args.size() < NumParams) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
return;
}
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
if (ArgIdx < NumParams) {
QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
false,
false,
getLangOpts().ObjCAutoRefCount);
if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
} else {
Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
if (EnableIfAttr *FailedAttr =
CheckEnableIf(Conversion, CandidateSet.getLocation(), None)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
}
void Sema::AddNonMemberOperatorCandidates(
const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
ArrayRef<Expr *> FunctionArgs = Args;
FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
FunctionDecl *FD =
FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D);
if (!CandidateSet.getRewriteInfo().isAcceptableCandidate(FD))
continue;
assert(!isa<CXXMethodDecl>(FD) &&
"unqualified operator lookup found a member function");
if (FunTmpl) {
AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs,
FunctionArgs, CandidateSet);
if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD))
AddTemplateOverloadCandidate(
FunTmpl, F.getPair(), ExplicitTemplateArgs,
{FunctionArgs[1], FunctionArgs[0]}, CandidateSet, false, false,
true, ADLCallKind::NotADL, OverloadCandidateParamOrder::Reversed);
} else {
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);
}
}
}
void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
OverloadCandidateParamOrder PO) {
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
QualType T1 = Args[0]->getType();
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
if (!isCompleteType(OpLoc, T1) && !T1Rec->isBeingDefined())
return;
if (!T1Rec->getDecl()->getDefinition())
return;
LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName);
LookupQualifiedName(Operators, T1Rec->getDecl());
Operators.suppressDiagnostics();
for (LookupResult::iterator Oper = Operators.begin(),
OperEnd = Operators.end();
Oper != OperEnd;
++Oper)
AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
Args[0]->Classify(Context), Args.slice(1),
CandidateSet, false, PO);
}
}
void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool IsAssignmentOperator,
unsigned NumContextualBoolArguments) {
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
Candidate.FoundDecl = DeclAccessPair::make(nullptr, AS_none);
Candidate.Function = nullptr;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes);
Candidate.Viable = true;
Candidate.ExplicitCallArguments = Args.size();
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
if (ArgIdx < NumContextualBoolArguments) {
assert(ParamTys[ArgIdx] == Context.BoolTy &&
"Contextual conversion to bool requires bool type");
Candidate.Conversions[ArgIdx]
= TryContextuallyConvertToBool(*this, Args[ArgIdx]);
} else {
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx],
ArgIdx == 0 && IsAssignmentOperator,
false,
getLangOpts().ObjCAutoRefCount);
}
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
break;
}
}
}
namespace {
class BuiltinCandidateTypeSet {
typedef llvm::SetVector<QualType, SmallVector<QualType, 8>,
llvm::SmallPtrSet<QualType, 8>> TypeSet;
TypeSet PointerTypes;
TypeSet MemberPointerTypes;
TypeSet EnumerationTypes;
TypeSet VectorTypes;
TypeSet MatrixTypes;
bool HasNonRecordTypes;
bool HasArithmeticOrEnumeralTypes;
bool HasNullPtrType;
Sema &SemaRef;
ASTContext &Context;
bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
const Qualifiers &VisibleQuals);
bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty);
public:
typedef TypeSet::iterator iterator;
BuiltinCandidateTypeSet(Sema &SemaRef)
: HasNonRecordTypes(false),
HasArithmeticOrEnumeralTypes(false),
HasNullPtrType(false),
SemaRef(SemaRef),
Context(SemaRef.Context) { }
void AddTypesConvertedFrom(QualType Ty,
SourceLocation Loc,
bool AllowUserConversions,
bool AllowExplicitConversions,
const Qualifiers &VisibleTypeConversionsQuals);
llvm::iterator_range<iterator> pointer_types() { return PointerTypes; }
llvm::iterator_range<iterator> member_pointer_types() {
return MemberPointerTypes;
}
llvm::iterator_range<iterator> enumeration_types() {
return EnumerationTypes;
}
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; }
};
}
bool
BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty,
const Qualifiers &VisibleQuals) {
if (!PointerTypes.insert(Ty))
return false;
QualType PointeeTy;
const PointerType *PointerTy = Ty->getAs<PointerType>();
bool buildObjCPtr = false;
if (!PointerTy) {
const ObjCObjectPointerType *PTy = Ty->castAs<ObjCObjectPointerType>();
PointeeTy = PTy->getPointeeType();
buildObjCPtr = true;
} else {
PointeeTy = PointerTy->getPointeeType();
}
if (PointeeTy->isArrayType())
return true;
unsigned BaseCVR = PointeeTy.getCVRQualifiers();
bool hasVolatile = VisibleQuals.hasVolatile();
bool hasRestrict = VisibleQuals.hasRestrict();
for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
if ((CVR | BaseCVR) != CVR) continue;
if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue;
if ((CVR & Qualifiers::Restrict) &&
(!hasRestrict ||
(!(PointeeTy->isAnyPointerType() || PointeeTy->isReferenceType()))))
continue;
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
QualType QPointerTy;
if (!buildObjCPtr)
QPointerTy = Context.getPointerType(QPointeeTy);
else
QPointerTy = Context.getObjCObjectPointerType(QPointeeTy);
PointerTypes.insert(QPointerTy);
}
return true;
}
bool
BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType Ty) {
if (!MemberPointerTypes.insert(Ty))
return false;
const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>();
assert(PointerTy && "type was not a member pointer type!");
QualType PointeeTy = PointerTy->getPointeeType();
if (PointeeTy->isArrayType())
return true;
const Type *ClassTy = PointerTy->getClass();
unsigned BaseCVR = PointeeTy.getCVRQualifiers();
for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {
if ((CVR | BaseCVR) != CVR) continue;
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
MemberPointerTypes.insert(
Context.getMemberPointerType(QPointeeTy, ClassTy));
}
return true;
}
void
BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
SourceLocation Loc,
bool AllowUserConversions,
bool AllowExplicitConversions,
const Qualifiers &VisibleQuals) {
Ty = Context.getCanonicalType(Ty);
if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>())
Ty = RefTy->getPointeeType();
if (Ty->isArrayType())
Ty = SemaRef.Context.getArrayDecayedType(Ty);
Ty = Ty.getLocalUnqualifiedType();
const RecordType *TyRec = Ty->getAs<RecordType>();
HasNonRecordTypes = HasNonRecordTypes || !TyRec;
HasArithmeticOrEnumeralTypes =
HasArithmeticOrEnumeralTypes || Ty->isArithmeticType();
if (Ty->isObjCIdType() || Ty->isObjCClassType())
PointerTypes.insert(Ty);
else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) {
if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))
return;
} else if (Ty->isMemberPointerType()) {
if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty))
return;
} else if (Ty->isEnumeralType()) {
HasArithmeticOrEnumeralTypes = true;
EnumerationTypes.insert(Ty);
} else if (Ty->isVectorType()) {
HasArithmeticOrEnumeralTypes = true;
VectorTypes.insert(Ty);
} else if (Ty->isMatrixType()) {
HasArithmeticOrEnumeralTypes = true;
MatrixTypes.insert(Ty);
} else if (Ty->isNullPtrType()) {
HasNullPtrType = true;
} else if (AllowUserConversions && TyRec) {
if (!SemaRef.isCompleteType(Loc, Ty))
return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (isa<FunctionTemplateDecl>(D))
continue;
CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
if (AllowExplicitConversions || !Conv->isExplicit()) {
AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,
VisibleQuals);
}
}
}
}
static QualType AdjustAddressSpaceForBuiltinOperandType(Sema &S, QualType T,
Expr *Arg) {
return S.Context.getAddrSpaceQualType(T, Arg->getType().getAddressSpace());
}
static void AddBuiltinAssignmentOperatorCandidates(Sema &S,
QualType T,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet) {
QualType ParamTypes[2];
ParamTypes[0] = S.Context.getLValueReferenceType(
AdjustAddressSpaceForBuiltinOperandType(S, T, Args[0]));
ParamTypes[1] = T;
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
true);
if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
ParamTypes[0] = S.Context.getLValueReferenceType(
AdjustAddressSpaceForBuiltinOperandType(S, S.Context.getVolatileType(T),
Args[0]));
ParamTypes[1] = T;
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
true);
}
}
static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) {
Qualifiers VRQuals;
const RecordType *TyRec;
if (const MemberPointerType *RHSMPType =
ArgExpr->getType()->getAs<MemberPointerType>())
TyRec = RHSMPType->getClass()->getAs<RecordType>();
else
TyRec = ArgExpr->getType()->getAs<RecordType>();
if (!TyRec) {
VRQuals.addVolatile();
VRQuals.addRestrict();
return VRQuals;
}
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
if (!ClassDecl->hasDefinition())
return VRQuals;
for (NamedDecl *D : ClassDecl->getVisibleConversionFunctions()) {
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) {
QualType CanTy = Context.getCanonicalType(Conv->getConversionType());
if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>())
CanTy = ResTypeRef->getPointeeType();
bool done = false;
while (!done) {
if (CanTy.isRestrictQualified())
VRQuals.addRestrict();
if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>())
CanTy = ResTypePtr->getPointeeType();
else if (const MemberPointerType *ResTypeMPtr =
CanTy->getAs<MemberPointerType>())
CanTy = ResTypeMPtr->getPointeeType();
else
done = true;
if (CanTy.isVolatileQualified())
VRQuals.addVolatile();
if (VRQuals.hasRestrict() && VRQuals.hasVolatile())
return VRQuals;
}
}
}
return VRQuals;
}
static void forAllQualifierCombinationsImpl(
QualifiersAndAtomic Available, QualifiersAndAtomic Applied,
llvm::function_ref<void(QualifiersAndAtomic)> Callback) {
if (Available.hasAtomic()) {
Available.removeAtomic();
forAllQualifierCombinationsImpl(Available, Applied.withAtomic(), Callback);
forAllQualifierCombinationsImpl(Available, Applied, Callback);
return;
}
if (Available.hasVolatile()) {
Available.removeVolatile();
assert(!Applied.hasVolatile());
forAllQualifierCombinationsImpl(Available, Applied.withVolatile(),
Callback);
forAllQualifierCombinationsImpl(Available, Applied, Callback);
return;
}
Callback(Applied);
}
static void forAllQualifierCombinations(
QualifiersAndAtomic Quals,
llvm::function_ref<void(QualifiersAndAtomic)> Callback) {
return forAllQualifierCombinationsImpl(Quals, QualifiersAndAtomic(),
Callback);
}
static QualType makeQualifiedLValueReferenceType(QualType Base,
QualifiersAndAtomic Quals,
Sema &S) {
if (Quals.hasAtomic())
Base = S.Context.getAtomicType(Base);
if (Quals.hasVolatile())
Base = S.Context.getVolatileType(Base);
return S.Context.getLValueReferenceType(Base);
}
namespace {
class BuiltinOperatorOverloadBuilder {
Sema &S;
ArrayRef<Expr *> Args;
QualifiersAndAtomic VisibleTypeConversionsQuals;
bool HasArithmeticOrEnumeralCandidateType;
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
OverloadCandidateSet &CandidateSet;
static constexpr int ArithmeticTypesCap = 24;
SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes;
unsigned FirstIntegralType,
LastIntegralType;
unsigned FirstPromotedIntegralType,
LastPromotedIntegralType;
unsigned FirstPromotedArithmeticType,
LastPromotedArithmeticType;
unsigned NumArithmeticTypes;
void InitArithmeticTypes() {
FirstPromotedArithmeticType = 0;
ArithmeticTypes.push_back(S.Context.FloatTy);
ArithmeticTypes.push_back(S.Context.DoubleTy);
ArithmeticTypes.push_back(S.Context.LongDoubleTy);
if (S.Context.getTargetInfo().hasFloat128Type())
ArithmeticTypes.push_back(S.Context.Float128Ty);
if (S.Context.getTargetInfo().hasIbm128Type())
ArithmeticTypes.push_back(S.Context.Ibm128Ty);
FirstIntegralType = ArithmeticTypes.size();
FirstPromotedIntegralType = ArithmeticTypes.size();
ArithmeticTypes.push_back(S.Context.IntTy);
ArithmeticTypes.push_back(S.Context.LongTy);
ArithmeticTypes.push_back(S.Context.LongLongTy);
if (S.Context.getTargetInfo().hasInt128Type() ||
(S.Context.getAuxTargetInfo() &&
S.Context.getAuxTargetInfo()->hasInt128Type()))
ArithmeticTypes.push_back(S.Context.Int128Ty);
ArithmeticTypes.push_back(S.Context.UnsignedIntTy);
ArithmeticTypes.push_back(S.Context.UnsignedLongTy);
ArithmeticTypes.push_back(S.Context.UnsignedLongLongTy);
if (S.Context.getTargetInfo().hasInt128Type() ||
(S.Context.getAuxTargetInfo() &&
S.Context.getAuxTargetInfo()->hasInt128Type()))
ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
LastPromotedIntegralType = ArithmeticTypes.size();
LastPromotedArithmeticType = ArithmeticTypes.size();
ArithmeticTypes.push_back(S.Context.BoolTy);
ArithmeticTypes.push_back(S.Context.CharTy);
ArithmeticTypes.push_back(S.Context.WCharTy);
if (S.Context.getLangOpts().Char8)
ArithmeticTypes.push_back(S.Context.Char8Ty);
ArithmeticTypes.push_back(S.Context.Char16Ty);
ArithmeticTypes.push_back(S.Context.Char32Ty);
ArithmeticTypes.push_back(S.Context.SignedCharTy);
ArithmeticTypes.push_back(S.Context.ShortTy);
ArithmeticTypes.push_back(S.Context.UnsignedCharTy);
ArithmeticTypes.push_back(S.Context.UnsignedShortTy);
LastIntegralType = ArithmeticTypes.size();
NumArithmeticTypes = ArithmeticTypes.size();
assert(ArithmeticTypes.size() <= ArithmeticTypesCap &&
"Enough inline storage for all arithmetic types.");
}
void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
bool HasVolatile,
bool HasRestrict) {
QualType ParamTypes[2] = {
S.Context.getLValueReferenceType(CandidateTy),
S.Context.IntTy
};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
if (HasVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(
S.Context.getVolatileType(CandidateTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
if (HasRestrict && CandidateTy->isAnyPointerType() &&
!CandidateTy.isRestrictQualified()) {
ParamTypes[0]
= S.Context.getLValueReferenceType(
S.Context.getCVRQualifiedType(CandidateTy, Qualifiers::Restrict));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
if (HasVolatile) {
ParamTypes[0]
= S.Context.getLValueReferenceType(
S.Context.getCVRQualifiedType(CandidateTy,
(Qualifiers::Volatile |
Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
}
void AddCandidate(QualType L, QualType R) {
QualType LandR[2] = {L, R};
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
public:
BuiltinOperatorOverloadBuilder(
Sema &S, ArrayRef<Expr *> Args,
QualifiersAndAtomic VisibleTypeConversionsQuals,
bool HasArithmeticOrEnumeralCandidateType,
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
OverloadCandidateSet &CandidateSet)
: S(S), Args(Args),
VisibleTypeConversionsQuals(VisibleTypeConversionsQuals),
HasArithmeticOrEnumeralCandidateType(
HasArithmeticOrEnumeralCandidateType),
CandidateTypes(CandidateTypes),
CandidateSet(CandidateSet) {
InitArithmeticTypes();
}
void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Arith = 0; Arith < NumArithmeticTypes; ++Arith) {
const auto TypeOfT = ArithmeticTypes[Arith];
if (TypeOfT == S.Context.BoolTy) {
if (Op == OO_MinusMinus)
continue;
if (Op == OO_PlusPlus && S.getLangOpts().CPlusPlus17)
continue;
}
addPlusPlusMinusMinusStyleOverloads(
TypeOfT,
VisibleTypeConversionsQuals.hasVolatile(),
VisibleTypeConversionsQuals.hasRestrict());
}
}
void addPlusPlusMinusMinusPointerOverloads() {
for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
if (!PtrTy->getPointeeType()->isObjectType())
continue;
addPlusPlusMinusMinusStyleOverloads(
PtrTy,
(!PtrTy.isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile()),
(!PtrTy.isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()));
}
}
void addUnaryStarPointerOverloads() {
for (QualType ParamTy : CandidateTypes[0].pointer_types()) {
QualType PointeeTy = ParamTy->getPointeeType();
if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
continue;
if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>())
if (Proto->getMethodQuals() || Proto->getRefQualifier())
continue;
S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet);
}
}
void addUnaryPlusOrMinusArithmeticOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Arith = FirstPromotedArithmeticType;
Arith < LastPromotedArithmeticType; ++Arith) {
QualType ArithTy = ArithmeticTypes[Arith];
S.AddBuiltinCandidate(&ArithTy, Args, CandidateSet);
}
for (QualType VecTy : CandidateTypes[0].vector_types())
S.AddBuiltinCandidate(&VecTy, Args, CandidateSet);
}
void addUnaryPlusPointerOverloads() {
for (QualType ParamTy : CandidateTypes[0].pointer_types())
S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet);
}
void addUnaryTildePromotedIntegralOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Int = FirstPromotedIntegralType;
Int < LastPromotedIntegralType; ++Int) {
QualType IntTy = ArithmeticTypes[Int];
S.AddBuiltinCandidate(&IntTy, Args, CandidateSet);
}
for (QualType VecTy : CandidateTypes[0].vector_types())
S.AddBuiltinCandidate(&VecTy, Args, CandidateSet);
}
void addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads() {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second)
continue;
QualType ParamTypes[2] = {MemPtrTy, MemPtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
if (CandidateTypes[ArgIdx].hasNullPtrType()) {
CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
if (AddedTypes.insert(NullPtrTy).second) {
QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
}
}
void addGenericBinaryPointerOrEnumeralOverloads(bool IsSpaceship) {
llvm::DenseSet<std::pair<CanQualType, CanQualType> >
UserDefinedBinaryOperators;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
if (!CandidateTypes[ArgIdx].enumeration_types().empty()) {
for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
CEnd = CandidateSet.end();
C != CEnd; ++C) {
if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
continue;
if (C->Function->isFunctionTemplateSpecialization())
continue;
bool Reversed = C->isReversed();
QualType FirstParamType = C->Function->getParamDecl(Reversed ? 1 : 0)
->getType()
.getUnqualifiedType();
QualType SecondParamType = C->Function->getParamDecl(Reversed ? 0 : 1)
->getType()
.getUnqualifiedType();
if (!FirstParamType->isEnumeralType() ||
!SecondParamType->isEnumeralType())
continue;
UserDefinedBinaryOperators.insert(
std::make_pair(S.Context.getCanonicalType(FirstParamType),
S.Context.getCanonicalType(SecondParamType)));
}
}
}
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
for (QualType PtrTy : CandidateTypes[ArgIdx].pointer_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
if (IsSpaceship && PtrTy->isFunctionPointerType())
continue;
QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
CanQualType CanonType = S.Context.getCanonicalType(EnumTy);
if (!AddedTypes.insert(CanonType).second ||
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
QualType ParamTypes[2] = {EnumTy, EnumTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
}
void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (int Arg = 0; Arg < 2; ++Arg) {
QualType AsymmetricParamTypes[2] = {
S.Context.getPointerDiffType(),
S.Context.getPointerDiffType(),
};
for (QualType PtrTy : CandidateTypes[Arg].pointer_types()) {
QualType PointeeTy = PtrTy->getPointeeType();
if (!PointeeTy->isObjectType())
continue;
AsymmetricParamTypes[Arg] = PtrTy;
if (Arg == 0 || Op == OO_Plus) {
S.AddBuiltinCandidate(AsymmetricParamTypes, Args, CandidateSet);
}
if (Op == OO_Minus) {
if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
}
}
void addGenericBinaryArithmeticOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Left = FirstPromotedArithmeticType;
Left < LastPromotedArithmeticType; ++Left) {
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
QualType LandR[2] = { ArithmeticTypes[Left],
ArithmeticTypes[Right] };
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
}
for (QualType Vec1Ty : CandidateTypes[0].vector_types())
for (QualType Vec2Ty : CandidateTypes[1].vector_types()) {
QualType LandR[2] = {Vec1Ty, Vec2Ty};
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
}
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);
}
}
void addThreeWayArithmeticOverloads() {
addGenericBinaryArithmeticOverloads();
}
void addBinaryBitwiseArithmeticOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Left = FirstPromotedIntegralType;
Left < LastPromotedIntegralType; ++Left) {
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
QualType LandR[2] = { ArithmeticTypes[Left],
ArithmeticTypes[Right] };
S.AddBuiltinCandidate(LandR, Args, CandidateSet);
}
}
}
void addAssignmentMemberPointerOrEnumeralOverloads() {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second)
continue;
AddBuiltinAssignmentOperatorCandidates(S, EnumTy, Args, CandidateSet);
}
for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second)
continue;
AddBuiltinAssignmentOperatorCandidates(S, MemPtrTy, Args, CandidateSet);
}
}
}
void addAssignmentPointerOverloads(bool isEqualOp) {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
if (isEqualOp)
AddedTypes.insert(S.Context.getCanonicalType(PtrTy));
else if (!PtrTy->getPointeeType()->isObjectType())
continue;
QualType ParamTypes[2] = {
S.Context.getLValueReferenceType(PtrTy),
isEqualOp ? PtrTy : S.Context.getPointerDiffType(),
};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
bool NeedVolatile = !PtrTy.isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile();
if (NeedVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(S.Context.getVolatileType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
}
if (!PtrTy.isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()) {
ParamTypes[0] =
S.Context.getLValueReferenceType(S.Context.getRestrictType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
if (NeedVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(S.Context.getCVRQualifiedType(
PtrTy, (Qualifiers::Volatile | Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
}
}
}
if (isEqualOp) {
for (QualType PtrTy : CandidateTypes[1].pointer_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
QualType ParamTypes[2] = {
S.Context.getLValueReferenceType(PtrTy),
PtrTy,
};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
true);
bool NeedVolatile = !PtrTy.isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile();
if (NeedVolatile) {
ParamTypes[0] = S.Context.getLValueReferenceType(
S.Context.getVolatileType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
true);
}
if (!PtrTy.isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()) {
ParamTypes[0] = S.Context.getLValueReferenceType(
S.Context.getRestrictType(PtrTy));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
true);
if (NeedVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(S.Context.getCVRQualifiedType(
PtrTy, (Qualifiers::Volatile | Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
true);
}
}
}
}
}
void addAssignmentArithmeticOverloads(bool isEqualOp) {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) {
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
QualType ParamTypes[2];
ParamTypes[1] = ArithmeticTypes[Right];
auto LeftBaseTy = AdjustAddressSpaceForBuiltinOperandType(
S, ArithmeticTypes[Left], Args[0]);
forAllQualifierCombinations(
VisibleTypeConversionsQuals, [&](QualifiersAndAtomic Quals) {
ParamTypes[0] =
makeQualifiedLValueReferenceType(LeftBaseTy, Quals, S);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
});
}
}
for (QualType Vec1Ty : CandidateTypes[0].vector_types())
for (QualType Vec2Ty : CandidateTypes[0].vector_types()) {
QualType ParamTypes[2];
ParamTypes[1] = Vec2Ty;
ParamTypes[0] = S.Context.getLValueReferenceType(Vec1Ty);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
if (VisibleTypeConversionsQuals.hasVolatile()) {
ParamTypes[0] = S.Context.getVolatileType(Vec1Ty);
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
isEqualOp);
}
}
}
void addAssignmentIntegralOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) {
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
QualType ParamTypes[2];
ParamTypes[1] = ArithmeticTypes[Right];
auto LeftBaseTy = AdjustAddressSpaceForBuiltinOperandType(
S, ArithmeticTypes[Left], Args[0]);
forAllQualifierCombinations(
VisibleTypeConversionsQuals, [&](QualifiersAndAtomic Quals) {
ParamTypes[0] =
makeQualifiedLValueReferenceType(LeftBaseTy, Quals, S);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
});
}
}
}
void addExclaimOverload() {
QualType ParamTy = S.Context.BoolTy;
S.AddBuiltinCandidate(&ParamTy, Args, CandidateSet,
false,
1);
}
void addAmpAmpOrPipePipeOverload() {
QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy };
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet,
false,
2);
}
void addSubscriptOverloads() {
for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
QualType ParamTypes[2] = {PtrTy, S.Context.getPointerDiffType()};
QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isObjectType())
continue;
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
for (QualType PtrTy : CandidateTypes[1].pointer_types()) {
QualType ParamTypes[2] = {S.Context.getPointerDiffType(), PtrTy};
QualType PointeeType = PtrTy->getPointeeType();
if (!PointeeType->isObjectType())
continue;
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
void addArrowStarOverloads() {
for (QualType PtrTy : CandidateTypes[0].pointer_types()) {
QualType C1Ty = PtrTy;
QualType C1;
QualifierCollector Q1;
C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0);
if (!isa<RecordType>(C1))
continue;
if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile())
continue;
if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
continue;
for (QualType MemPtrTy : CandidateTypes[1].member_pointer_types()) {
const MemberPointerType *mptr = cast<MemberPointerType>(MemPtrTy);
QualType C2 = QualType(mptr->getClass(), 0);
C2 = C2.getUnqualifiedType();
if (C1 != C2 && !S.IsDerivedFrom(CandidateSet.getLocation(), C1, C2))
break;
QualType ParamTypes[2] = {PtrTy, MemPtrTy};
QualType T = mptr->getPointeeType();
if (!VisibleTypeConversionsQuals.hasVolatile() &&
T.isVolatileQualified())
continue;
if (!VisibleTypeConversionsQuals.hasRestrict() &&
T.isRestrictQualified())
continue;
T = Q1.apply(S.Context, T);
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
}
void addConditionalOperatorOverloads() {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
for (QualType PtrTy : CandidateTypes[ArgIdx].pointer_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(PtrTy)).second)
continue;
QualType ParamTypes[2] = {PtrTy, PtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
for (QualType MemPtrTy : CandidateTypes[ArgIdx].member_pointer_types()) {
if (!AddedTypes.insert(S.Context.getCanonicalType(MemPtrTy)).second)
continue;
QualType ParamTypes[2] = {MemPtrTy, MemPtrTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
if (S.getLangOpts().CPlusPlus11) {
for (QualType EnumTy : CandidateTypes[ArgIdx].enumeration_types()) {
if (!EnumTy->castAs<EnumType>()->getDecl()->isScoped())
continue;
if (!AddedTypes.insert(S.Context.getCanonicalType(EnumTy)).second)
continue;
QualType ParamTypes[2] = {EnumTy, EnumTy};
S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet);
}
}
}
}
};
}
void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet) {
QualifiersAndAtomic VisibleTypeConversionsQuals;
VisibleTypeConversionsQuals.addConst();
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
if (Args[ArgIdx]->getType()->isAtomicType())
VisibleTypeConversionsQuals.addAtomic();
}
bool HasNonRecordCandidateType = false;
bool HasArithmeticOrEnumeralCandidateType = false;
SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
CandidateTypes.emplace_back(*this);
CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
OpLoc,
true,
(Op == OO_Exclaim ||
Op == OO_AmpAmp ||
Op == OO_PipePipe),
VisibleTypeConversionsQuals);
HasNonRecordCandidateType = HasNonRecordCandidateType ||
CandidateTypes[ArgIdx].hasNonRecordTypes();
HasArithmeticOrEnumeralCandidateType =
HasArithmeticOrEnumeralCandidateType ||
CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes();
}
if (!HasNonRecordCandidateType &&
!(Op == OO_Exclaim || Op == OO_AmpAmp || Op == OO_PipePipe))
return;
BuiltinOperatorOverloadBuilder OpBuilder(*this, Args,
VisibleTypeConversionsQuals,
HasArithmeticOrEnumeralCandidateType,
CandidateTypes, CandidateSet);
switch (Op) {
case OO_None:
case NUM_OVERLOADED_OPERATORS:
llvm_unreachable("Expected an overloaded operator");
case OO_New:
case OO_Delete:
case OO_Array_New:
case OO_Array_Delete:
case OO_Call:
llvm_unreachable(
"Special operators don't use AddBuiltinOperatorCandidates");
case OO_Comma:
case OO_Arrow:
case OO_Coawait:
break;
case OO_Plus: if (Args.size() == 1)
OpBuilder.addUnaryPlusPointerOverloads();
LLVM_FALLTHROUGH;
case OO_Minus: if (Args.size() == 1) {
OpBuilder.addUnaryPlusOrMinusArithmeticOverloads();
} else {
OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
OpBuilder.addGenericBinaryArithmeticOverloads();
OpBuilder.addMatrixBinaryArithmeticOverloads();
}
break;
case OO_Star: if (Args.size() == 1)
OpBuilder.addUnaryStarPointerOverloads();
else {
OpBuilder.addGenericBinaryArithmeticOverloads();
OpBuilder.addMatrixBinaryArithmeticOverloads();
}
break;
case OO_Slash:
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_PlusPlus:
case OO_MinusMinus:
OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op);
OpBuilder.addPlusPlusMinusMinusPointerOverloads();
break;
case OO_EqualEqual:
case OO_ExclaimEqual:
OpBuilder.addEqualEqualOrNotEqualMemberPointerOrNullptrOverloads();
OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(false);
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_Less:
case OO_Greater:
case OO_LessEqual:
case OO_GreaterEqual:
OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(false);
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
case OO_Spaceship:
OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(true);
OpBuilder.addThreeWayArithmeticOverloads();
break;
case OO_Percent:
case OO_Caret:
case OO_Pipe:
case OO_LessLess:
case OO_GreaterGreater:
OpBuilder.addBinaryBitwiseArithmeticOverloads();
break;
case OO_Amp: if (Args.size() == 1)
break;
OpBuilder.addBinaryBitwiseArithmeticOverloads();
break;
case OO_Tilde:
OpBuilder.addUnaryTildePromotedIntegralOverloads();
break;
case OO_Equal:
OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
LLVM_FALLTHROUGH;
case OO_PlusEqual:
case OO_MinusEqual:
OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
LLVM_FALLTHROUGH;
case OO_StarEqual:
case OO_SlashEqual:
OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal);
break;
case OO_PercentEqual:
case OO_LessLessEqual:
case OO_GreaterGreaterEqual:
case OO_AmpEqual:
case OO_CaretEqual:
case OO_PipeEqual:
OpBuilder.addAssignmentIntegralOverloads();
break;
case OO_Exclaim:
OpBuilder.addExclaimOverload();
break;
case OO_AmpAmp:
case OO_PipePipe:
OpBuilder.addAmpAmpOrPipePipeOverload();
break;
case OO_Subscript:
if (Args.size() == 2)
OpBuilder.addSubscriptOverloads();
break;
case OO_ArrowStar:
OpBuilder.addArrowStarOverloads();
break;
case OO_Conditional:
OpBuilder.addConditionalOperatorOverloads();
OpBuilder.addGenericBinaryArithmeticOverloads();
break;
}
}
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
SourceLocation Loc,
ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
ADLResult Fns;
ArgumentDependentLookup(Name, Loc, Args, Fns);
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
Cand != CandEnd; ++Cand)
if (Cand->Function) {
Fns.erase(Cand->Function);
if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
Fns.erase(FunTmpl);
}
for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
if (ExplicitTemplateArgs)
continue;
AddOverloadCandidate(
FD, FoundDecl, Args, CandidateSet, false,
PartialOverloading, true,
false, ADLCallKind::UsesADL);
if (CandidateSet.getRewriteInfo().shouldAddReversed(Context, FD)) {
AddOverloadCandidate(
FD, FoundDecl, {Args[1], Args[0]}, CandidateSet,
false, PartialOverloading,
true, false,
ADLCallKind::UsesADL, None, OverloadCandidateParamOrder::Reversed);
}
} else {
auto *FTD = cast<FunctionTemplateDecl>(*I);
AddTemplateOverloadCandidate(
FTD, FoundDecl, ExplicitTemplateArgs, Args, CandidateSet,
false, PartialOverloading,
true, ADLCallKind::UsesADL);
if (CandidateSet.getRewriteInfo().shouldAddReversed(
Context, FTD->getTemplatedDecl())) {
AddTemplateOverloadCandidate(
FTD, FoundDecl, ExplicitTemplateArgs, {Args[1], Args[0]},
CandidateSet, false, PartialOverloading,
true, ADLCallKind::UsesADL,
OverloadCandidateParamOrder::Reversed);
}
}
}
}
namespace {
enum class Comparison { Equal, Better, Worse };
}
static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1,
const FunctionDecl *Cand2) {
bool Cand1Attr = Cand1->hasAttr<EnableIfAttr>();
bool Cand2Attr = Cand2->hasAttr<EnableIfAttr>();
if (!Cand1Attr || !Cand2Attr) {
if (Cand1Attr == Cand2Attr)
return Comparison::Equal;
return Cand1Attr ? Comparison::Better : Comparison::Worse;
}
auto Cand1Attrs = Cand1->specific_attrs<EnableIfAttr>();
auto Cand2Attrs = Cand2->specific_attrs<EnableIfAttr>();
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);
if (!Cand1A)
return Comparison::Worse;
if (!Cand2A)
return Comparison::Better;
Cand1ID.clear();
Cand2ID.clear();
(*Cand1A)->getCond()->Profile(Cand1ID, S.getASTContext(), true);
(*Cand2A)->getCond()->Profile(Cand2ID, S.getASTContext(), true);
if (Cand1ID != Cand2ID)
return Comparison::Worse;
}
return Comparison::Equal;
}
static Comparison
isBetterMultiversionCandidate(const OverloadCandidate &Cand1,
const OverloadCandidate &Cand2) {
if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function ||
!Cand2.Function->isMultiVersion())
return Comparison::Equal;
if (Cand1.Function->isInvalidDecl()) {
if (Cand2.Function->isInvalidDecl())
return Comparison::Equal;
return Comparison::Worse;
}
if (Cand2.Function->isInvalidDecl())
return Comparison::Better;
bool Cand1CPUDisp = Cand1.Function->hasAttr<CPUDispatchAttr>();
bool Cand2CPUDisp = Cand2.Function->hasAttr<CPUDispatchAttr>();
const auto *Cand1CPUSpec = Cand1.Function->getAttr<CPUSpecificAttr>();
const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>();
if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec)
return Comparison::Equal;
if (Cand1CPUDisp && !Cand2CPUDisp)
return Comparison::Better;
if (Cand2CPUDisp && !Cand1CPUDisp)
return Comparison::Worse;
if (Cand1CPUSpec && Cand2CPUSpec) {
if (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(
Cand1CPUSpec->cpus_begin(), Cand1CPUSpec->cpus_end(),
Cand2CPUSpec->cpus_begin(),
[](const IdentifierInfo *LHS, const IdentifierInfo *RHS) {
return LHS->getName() == RHS->getName();
});
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()
? Comparison::Better
: Comparison::Worse;
}
llvm_unreachable("No way to get here unless both had cpu_dispatch");
}
static Optional<QualType> getImplicitObjectParamType(ASTContext &Context,
const FunctionDecl *F) {
if (!isa<CXXMethodDecl>(F) || isa<CXXConstructorDecl>(F))
return llvm::None;
auto *M = cast<CXXMethodDecl>(F);
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);
assert(!T1.isNull() && !T2.isNull() && "Unexpected null param types");
if (!Context.hasSameUnqualifiedType(T1, T2))
return false;
}
return true;
}
static bool canCompareFunctionConstraints(Sema &S,
const OverloadCandidate &Cand1,
const OverloadCandidate &Cand2) {
if (Cand1.Function && Cand2.Function && Cand1.Function->hasPrototype() &&
Cand2.Function->hasPrototype()) {
auto *PT1 = cast<FunctionProtoType>(Cand1.Function->getFunctionType());
auto *PT2 = cast<FunctionProtoType>(Cand2.Function->getFunctionType());
if (PT1->getNumParams() == PT2->getNumParams() &&
PT1->isVariadic() == PT2->isVariadic() &&
S.FunctionParamTypesAreEqual(PT1, PT2, nullptr,
Cand1.isReversed() ^ Cand2.isReversed()))
return true;
}
return false;
}
bool clang::isBetterOverloadCandidate(
Sema &S, const OverloadCandidate &Cand1, const OverloadCandidate &Cand2,
SourceLocation Loc, OverloadCandidateSet::CandidateSetKind Kind) {
if (!Cand2.Viable)
return Cand1.Viable;
else if (!Cand1.Viable)
return false;
if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function &&
S.getLangOpts().GPUExcludeWrongSideOverloads) {
if (FunctionDecl *Caller = S.getCurFunctionDecl(true)) {
bool IsCallerImplicitHD = Sema::isCUDAImplicitHostDeviceFunction(Caller);
bool IsCand1ImplicitHD =
Sema::isCUDAImplicitHostDeviceFunction(Cand1.Function);
bool IsCand2ImplicitHD =
Sema::isCUDAImplicitHostDeviceFunction(Cand2.Function);
auto P1 = S.IdentifyCUDAPreference(Caller, Cand1.Function);
auto P2 = S.IdentifyCUDAPreference(Caller, Cand2.Function);
assert(P1 != Sema::CFP_Never && P2 != Sema::CFP_Never);
auto EmitThreshold =
(S.getLangOpts().CUDAIsDevice && IsCallerImplicitHD &&
(IsCand1ImplicitHD || IsCand2ImplicitHD))
? Sema::CFP_Never
: Sema::CFP_WrongSide;
auto Cand1Emittable = P1 > EmitThreshold;
auto Cand2Emittable = P2 > EmitThreshold;
if (Cand1Emittable && !Cand2Emittable)
return true;
if (!Cand1Emittable && Cand2Emittable)
return false;
}
}
unsigned StartArg = 0;
if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
StartArg = 1;
auto IsIllFormedConversion = [&](const ImplicitConversionSequence &ICS) {
if (!S.getLangOpts().CPlusPlus)
return ICS.isStandard() &&
ICS.Standard.Second == ICK_Incompatible_Pointer_Conversion;
return S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
hasDeprecatedStringLiteralToCharPtrConversion(ICS);
};
unsigned NumArgs = Cand1.Conversions.size();
assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch");
bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
bool Cand1Bad = IsIllFormedConversion(Cand1.Conversions[ArgIdx]);
bool Cand2Bad = IsIllFormedConversion(Cand2.Conversions[ArgIdx]);
if (Cand1Bad != Cand2Bad) {
if (Cand1Bad)
return false;
HasBetterConversion = true;
}
}
if (HasBetterConversion)
return true;
bool HasWorseConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
switch (CompareImplicitConversionSequences(S, Loc,
Cand1.Conversions[ArgIdx],
Cand2.Conversions[ArgIdx])) {
case ImplicitConversionSequence::Better:
HasBetterConversion = true;
break;
case ImplicitConversionSequence::Worse:
if (Cand1.Function && Cand2.Function &&
Cand1.isReversed() != Cand2.isReversed() &&
haveSameParameterTypes(S.Context, Cand1.Function, Cand2.Function,
NumArgs)) {
HasWorseConversion = true;
break;
}
return false;
case ImplicitConversionSequence::Indistinguishable:
break;
}
}
if (HasBetterConversion && !HasWorseConversion)
return true;
if (Kind == OverloadCandidateSet::CSK_InitByUserDefinedConversion &&
Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
ImplicitConversionSequence::CompareKind Result =
compareConversionFunctions(S, Cand1.Function, Cand2.Function);
if (Result == ImplicitConversionSequence::Indistinguishable)
Result = CompareStandardConversionSequences(S, Loc,
Cand1.FinalConversion,
Cand2.FinalConversion);
if (Result != ImplicitConversionSequence::Indistinguishable)
return Result == ImplicitConversionSequence::Better;
}
if (Kind == OverloadCandidateSet::CSK_InitByConstructor && NumArgs == 1 &&
Cand1.Function && Cand2.Function &&
isa<CXXConstructorDecl>(Cand1.Function) !=
isa<CXXConstructorDecl>(Cand2.Function))
return isa<CXXConstructorDecl>(Cand1.Function);
bool Cand1IsSpecialization = Cand1.Function &&
Cand1.Function->getPrimaryTemplate();
bool Cand2IsSpecialization = Cand2.Function &&
Cand2.Function->getPrimaryTemplate();
if (Cand1IsSpecialization != Cand2IsSpecialization)
return Cand2IsSpecialization;
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,
Cand1.isReversed() ^ Cand2.isReversed(),
canCompareFunctionConstraints(S, Cand1, Cand2)))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
if (!Cand1IsSpecialization && !Cand2IsSpecialization &&
canCompareFunctionConstraints(S, Cand1, Cand2)) {
Expr *RC1 = Cand1.Function->getTrailingRequiresClause();
Expr *RC2 = Cand2.Function->getTrailingRequiresClause();
if (RC1 && RC2) {
bool AtLeastAsConstrained1, AtLeastAsConstrained2;
if (S.IsAtLeastAsConstrained(Cand1.Function, {RC1}, Cand2.Function, {RC2},
AtLeastAsConstrained1) ||
S.IsAtLeastAsConstrained(Cand2.Function, {RC2}, Cand1.Function, {RC1},
AtLeastAsConstrained2))
return false;
if (AtLeastAsConstrained1 != AtLeastAsConstrained2)
return AtLeastAsConstrained1;
} else if (RC1 || RC2) {
return RC1 != nullptr;
}
}
bool Cand1IsInherited =
isa_and_nonnull<ConstructorUsingShadowDecl>(Cand1.FoundDecl.getDecl());
bool Cand2IsInherited =
isa_and_nonnull<ConstructorUsingShadowDecl>(Cand2.FoundDecl.getDecl());
if (Cand1IsInherited != Cand2IsInherited)
return Cand2IsInherited;
else if (Cand1IsInherited) {
assert(Cand2IsInherited);
auto *Cand1Class = cast<CXXRecordDecl>(Cand1.Function->getDeclContext());
auto *Cand2Class = cast<CXXRecordDecl>(Cand2.Function->getDeclContext());
if (Cand1Class->isDerivedFrom(Cand2Class))
return true;
if (Cand2Class->isDerivedFrom(Cand1Class))
return false;
}
if (Cand1.RewriteKind != Cand2.RewriteKind)
return Cand1.RewriteKind < Cand2.RewriteKind;
{
auto *Guide1 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand1.Function);
auto *Guide2 = dyn_cast_or_null<CXXDeductionGuideDecl>(Cand2.Function);
if (Guide1 && Guide2) {
if (Guide1->isImplicit() != Guide2->isImplicit())
return Guide2->isImplicit();
if (Guide1->isCopyDeductionCandidate())
return true;
}
}
if (Cand1.Function && Cand2.Function) {
Comparison Cmp = compareEnableIfAttrs(S, Cand1.Function, Cand2.Function);
if (Cmp != Comparison::Equal)
return Cmp == Comparison::Better;
}
bool HasPS1 = Cand1.Function != nullptr &&
functionHasPassObjectSizeParams(Cand1.Function);
bool HasPS2 = Cand2.Function != nullptr &&
functionHasPassObjectSizeParams(Cand2.Function);
if (HasPS1 != HasPS2 && HasPS1)
return true;
auto MV = isBetterMultiversionCandidate(Cand1, Cand2);
if (MV == Comparison::Better)
return true;
if (MV == Comparison::Worse)
return false;
if (S.getLangOpts().CUDA && Cand1.Function && Cand2.Function) {
FunctionDecl *Caller = S.getCurFunctionDecl(true);
return S.IdentifyCUDAPreference(Caller, Cand1.Function) >
S.IdentifyCUDAPreference(Caller, Cand2.Function);
}
const auto *CD1 = dyn_cast_or_null<CXXConstructorDecl>(Cand1.Function);
const auto *CD2 = dyn_cast_or_null<CXXConstructorDecl>(Cand2.Function);
if (CD1 && CD2) {
LangAS AS1 = CD1->getMethodQualifiers().getAddressSpace();
LangAS AS2 = CD2->getMethodQualifiers().getAddressSpace();
if (AS1 != AS2) {
if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
return true;
if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
return false;
}
}
return false;
}
bool Sema::isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
const NamedDecl *B) {
auto *VA = dyn_cast_or_null<ValueDecl>(A);
auto *VB = dyn_cast_or_null<ValueDecl>(B);
if (!VA || !VB)
return false;
if (!VA->getDeclContext()->getRedeclContext()->Equals(
VB->getDeclContext()->getRedeclContext()) ||
getOwningModule(VA) == getOwningModule(VB) ||
VA->isExternallyVisible() || VB->isExternallyVisible())
return false;
if (Context.hasSameType(VA->getType(), VB->getType()))
return true;
if (auto *EA = dyn_cast<EnumConstantDecl>(VA)) {
if (auto *EB = dyn_cast<EnumConstantDecl>(VB)) {
auto *EnumA = cast<EnumDecl>(EA->getDeclContext());
auto *EnumB = cast<EnumDecl>(EB->getDeclContext());
if (EnumA->hasNameForLinkage() || EnumB->hasNameForLinkage() ||
!Context.hasSameType(EnumA->getIntegerType(),
EnumB->getIntegerType()))
return false;
return llvm::APSInt::isSameValue(EA->getInitVal(), EB->getInitVal());
}
}
return false;
}
void Sema::diagnoseEquivalentInternalLinkageDeclarations(
SourceLocation Loc, const NamedDecl *D, ArrayRef<const NamedDecl *> Equiv) {
assert(D && "Unknown declaration");
Diag(Loc, diag::ext_equivalent_internal_linkage_decl_in_modules) << D;
Module *M = getOwningModule(D);
Diag(D->getLocation(), diag::note_equivalent_internal_linkage_decl)
<< !M << (M ? M->getFullModuleName() : "");
for (auto *E : Equiv) {
Module *M = getOwningModule(E);
Diag(E->getLocation(), diag::note_equivalent_internal_linkage_decl)
<< !M << (M ? M->getFullModuleName() : "");
}
}
OverloadingResult
OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
iterator &Best) {
llvm::SmallVector<OverloadCandidate *, 16> Candidates;
std::transform(begin(), end(), std::back_inserter(Candidates),
[](OverloadCandidate &Cand) { return &Cand; });
if (S.getLangOpts().CUDA && !S.getLangOpts().GPUExcludeWrongSideOverloads) {
const FunctionDecl *Caller = S.getCurFunctionDecl(true);
bool ContainsSameSideCandidate =
llvm::any_of(Candidates, [&](OverloadCandidate *Cand) {
return Cand->Viable && Cand->Function &&
S.IdentifyCUDAPreference(Caller, Cand->Function) ==
Sema::CFP_SameSide;
});
if (ContainsSameSideCandidate) {
auto IsWrongSideCandidate = [&](OverloadCandidate *Cand) {
return Cand->Viable && Cand->Function &&
S.IdentifyCUDAPreference(Caller, Cand->Function) ==
Sema::CFP_WrongSide;
};
llvm::erase_if(Candidates, IsWrongSideCandidate);
}
}
Best = end();
for (auto *Cand : Candidates) {
Cand->Best = false;
if (Cand->Viable)
if (Best == end() ||
isBetterOverloadCandidate(S, *Cand, *Best, Loc, Kind))
Best = Cand;
}
if (Best == end())
return OR_No_Viable_Function;
llvm::SmallVector<const NamedDecl *, 4> EquivalentCands;
llvm::SmallVector<OverloadCandidate*, 4> PendingBest;
PendingBest.push_back(&*Best);
Best->Best = true;
while (!PendingBest.empty()) {
auto *Curr = PendingBest.pop_back_val();
for (auto *Cand : Candidates) {
if (Cand->Viable && !Cand->Best &&
!isBetterOverloadCandidate(S, *Curr, *Cand, Loc, Kind)) {
PendingBest.push_back(Cand);
Cand->Best = true;
if (S.isEquivalentInternalLinkageDeclaration(Cand->Function,
Curr->Function))
EquivalentCands.push_back(Cand->Function);
else
Best = end();
}
}
}
if (Best == end())
return OR_Ambiguous;
if (Best->Function && Best->Function->isDeleted())
return OR_Deleted;
if (!EquivalentCands.empty())
S.diagnoseEquivalentInternalLinkageDeclarations(Loc, Best->Function,
EquivalentCands);
return OR_Success;
}
namespace {
enum OverloadCandidateKind {
oc_function,
oc_method,
oc_reversed_binary_operator,
oc_constructor,
oc_implicit_default_constructor,
oc_implicit_copy_constructor,
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
oc_implicit_equality_comparison,
oc_inherited_constructor
};
enum OverloadCandidateSelect {
ocs_non_template,
ocs_template,
ocs_described_template,
};
static std::pair<OverloadCandidateKind, OverloadCandidateSelect>
ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn,
OverloadCandidateRewriteKind CRK,
std::string &Description) {
bool isTemplate = Fn->isTemplateDecl() || Found->isTemplateDecl();
if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
isTemplate = true;
Description = S.getTemplateArgumentBindingsText(
FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
}
OverloadCandidateSelect Select = [&]() {
if (!Description.empty())
return ocs_described_template;
return isTemplate ? ocs_template : ocs_non_template;
}();
OverloadCandidateKind Kind = [&]() {
if (Fn->isImplicit() && Fn->getOverloadedOperator() == OO_EqualEqual)
return oc_implicit_equality_comparison;
if (CRK & CRK_Reversed)
return oc_reversed_binary_operator;
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
if (!Ctor->isImplicit()) {
if (isa<ConstructorUsingShadowDecl>(Found))
return oc_inherited_constructor;
else
return oc_constructor;
}
if (Ctor->isDefaultConstructor())
return oc_implicit_default_constructor;
if (Ctor->isMoveConstructor())
return oc_implicit_move_constructor;
assert(Ctor->isCopyConstructor() &&
"unexpected sort of implicit constructor");
return oc_implicit_copy_constructor;
}
if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
if (!Meth->isImplicit())
return oc_method;
if (Meth->isMoveAssignmentOperator())
return oc_implicit_move_assignment;
if (Meth->isCopyAssignmentOperator())
return oc_implicit_copy_assignment;
assert(isa<CXXConversionDecl>(Meth) && "expected conversion");
return oc_method;
}
return oc_function;
}();
return std::make_pair(Kind, Select);
}
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) {
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl))
S.Diag(FoundDecl->getLocation(),
diag::note_ovl_candidate_inherited_constructor)
<< Shadow->getNominatedBaseClass();
}
}
static bool isFunctionAlwaysEnabled(const ASTContext &Ctx,
const FunctionDecl *FD) {
for (auto *EnableIf : FD->specific_attrs<EnableIfAttr>()) {
bool AlwaysTrue;
if (EnableIf->getCond()->isValueDependent() ||
!EnableIf->getCond()->EvaluateAsBooleanCondition(AlwaysTrue, Ctx))
return false;
if (!AlwaysTrue)
return false;
}
return true;
}
static bool checkAddressOfFunctionIsAvailable(Sema &S, const FunctionDecl *FD,
bool Complain,
bool InOverloadResolution,
SourceLocation Loc) {
if (!isFunctionAlwaysEnabled(S.Context, FD)) {
if (Complain) {
if (InOverloadResolution)
S.Diag(FD->getBeginLoc(),
diag::note_addrof_ovl_candidate_disabled_by_enable_if_attr);
else
S.Diag(Loc, diag::err_addrof_function_disabled_by_enable_if_attr) << FD;
}
return false;
}
if (FD->getTrailingRequiresClause()) {
ConstraintSatisfaction Satisfaction;
if (S.CheckFunctionConstraints(FD, Satisfaction, Loc))
return false;
if (!Satisfaction.IsSatisfied) {
if (Complain) {
if (InOverloadResolution) {
SmallString<128> TemplateArgString;
if (FunctionTemplateDecl *FunTmpl = FD->getPrimaryTemplate()) {
TemplateArgString += " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
FunTmpl->getTemplateParameters(),
*FD->getTemplateSpecializationArgs());
}
S.Diag(FD->getBeginLoc(),
diag::note_ovl_candidate_unsatisfied_constraints)
<< TemplateArgString;
} else
S.Diag(Loc, diag::err_addrof_function_constraints_not_satisfied)
<< FD;
S.DiagnoseUnsatisfiedConstraint(Satisfaction);
}
return false;
}
}
auto I = llvm::find_if(FD->parameters(), [](const ParmVarDecl *P) {
return P->hasAttr<PassObjectSizeAttr>();
});
if (I == FD->param_end())
return true;
if (Complain) {
unsigned ParamNo = std::distance(FD->param_begin(), I) + 1;
if (InOverloadResolution)
S.Diag(FD->getLocation(),
diag::note_ovl_candidate_has_pass_object_size_params)
<< ParamNo;
else
S.Diag(Loc, diag::err_address_of_function_with_pass_object_size_params)
<< FD << ParamNo;
}
return false;
}
static bool checkAddressOfCandidateIsAvailable(Sema &S,
const FunctionDecl *FD) {
return checkAddressOfFunctionIsAvailable(S, FD, true,
true,
SourceLocation());
}
bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
bool Complain,
SourceLocation Loc) {
return ::checkAddressOfFunctionIsAvailable(*this, Function, Complain,
false,
Loc);
}
static bool shouldSkipNotingLambdaConversionDecl(FunctionDecl *Fn) {
const auto *ConvD = dyn_cast<CXXConversionDecl>(Fn);
if (!ConvD)
return false;
const auto *RD = cast<CXXRecordDecl>(Fn->getParent());
if (!RD->isLambda())
return false;
CXXMethodDecl *CallOp = RD->getLambdaCallOperator();
CallingConv CallOpCC =
CallOp->getType()->castAs<FunctionType>()->getCallConv();
QualType ConvRTy = ConvD->getType()->castAs<FunctionType>()->getReturnType();
CallingConv ConvToCC =
ConvRTy->getPointeeType()->castAs<FunctionType>()->getCallConv();
return ConvToCC != CallOpCC;
}
void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
OverloadCandidateRewriteKind RewriteKind,
QualType DestType, bool TakingAddress) {
if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
return;
if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() &&
!Fn->getAttr<TargetAttr>()->isDefaultVersion())
return;
if (shouldSkipNotingLambdaConversionDecl(Fn))
return;
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair =
ClassifyOverloadCandidate(*this, Found, Fn, RewriteKind, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
<< (unsigned)KSPair.first << (unsigned)KSPair.second
<< Fn << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
MaybeEmitInheritedConstructorNote(*this, Found);
}
static void
MaybeDiagnoseAmbiguousConstraints(Sema &S, ArrayRef<OverloadCandidate> Cands) {
SmallVector<const Expr *, 3> FirstAC, SecondAC;
FunctionDecl *FirstCand = nullptr, *SecondCand = nullptr;
for (auto I = Cands.begin(), E = Cands.end(); I != E; ++I) {
if (!I->Function)
continue;
SmallVector<const Expr *, 3> AC;
if (auto *Template = I->Function->getPrimaryTemplate())
Template->getAssociatedConstraints(AC);
else
I->Function->getAssociatedConstraints(AC);
if (AC.empty())
continue;
if (FirstCand == nullptr) {
FirstCand = I->Function;
FirstAC = AC;
} else if (SecondCand == nullptr) {
SecondCand = I->Function;
SecondAC = AC;
} else {
return;
}
}
if (!SecondCand)
return;
if (S.MaybeEmitAmbiguousAtomicConstraintsDiagnostic(FirstCand, FirstAC,
SecondCand, SecondAC))
return;
}
void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType,
bool TakingAddress) {
assert(OverloadedExpr->getType() == Context.OverloadTy);
OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr);
OverloadExpr *OvlExpr = Ovl.Expression;
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
IEnd = OvlExpr->decls_end();
I != IEnd; ++I) {
if (FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), CRK_None, DestType,
TakingAddress);
} else if (FunctionDecl *Fun
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
NoteOverloadCandidate(*I, Fun, CRK_None, DestType, TakingAddress);
}
}
}
void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
Sema &S,
SourceLocation CaretLoc,
const PartialDiagnostic &PDiag) const {
S.Diag(CaretLoc, PDiag)
<< Ambiguous.getFromType() << Ambiguous.getToType();
unsigned CandsShown = 0;
AmbiguousConversionSequence::const_iterator I, E;
for (I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) {
if (CandsShown >= S.Diags.getNumOverloadCandidatesToShow())
break;
++CandsShown;
S.NoteOverloadCandidate(I->first, I->second);
}
S.Diags.overloadCandidatesShown(CandsShown);
if (I != E)
S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I);
}
static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
unsigned I, bool TakingCandidateAddress) {
const ImplicitConversionSequence &Conv = Cand->Conversions[I];
assert(Conv.isBad());
assert(Cand->Function && "for now, candidate must be a function");
FunctionDecl *Fn = Cand->Function;
bool isObjectArgument = false;
if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn)) {
if (I == 0)
isObjectArgument = true;
else
I--;
}
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, Cand->getRewriteKind(),
FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
QualType FromTy = Conv.Bad.getFromType();
QualType ToTy = Conv.Bad.getToType();
if (FromTy == S.Context.OverloadTy) {
assert(FromExpr && "overload set argument came from implicit argument?");
Expr *E = FromExpr->IgnoreParens();
if (isa<UnaryOperator>(E))
E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
DeclarationName Name = cast<OverloadExpr>(E)->getName();
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy
<< Name << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
CanQualType CToTy = S.Context.getCanonicalType(ToTy);
if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
CToTy = RT->getPointeeType();
else {
if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>()) {
CFromTy = FromPT->getPointeeType();
CToTy = ToPT->getPointeeType();
}
}
if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
!CToTy.isAtLeastAsQualifiedAs(CFromTy)) {
Qualifiers FromQs = CFromTy.getQualifiers();
Qualifiers ToQs = CToTy.getQualifiers();
if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
if (isObjectArgument)
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace_this)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
<< FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromQs.getAddressSpace() << ToQs.getAddressSpace();
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
<< FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromQs.getAddressSpace() << ToQs.getAddressSpace()
<< ToTy->isReferenceType() << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
<< (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
<< (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromQs.hasUnaligned() != ToQs.hasUnaligned()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_unaligned)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< FromQs.hasUnaligned() << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
assert(CVR && "expected qualifiers mismatch");
if (isObjectArgument) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< (CVR - 1);
} else {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< (CVR - 1) << I + 1;
}
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (Conv.Bad.Kind == BadConversionSequence::lvalue_ref_to_rvalue ||
Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_value_category)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (unsigned)isObjectArgument << I + 1
<< (Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue)
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange());
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (FromExpr && isa<InitListExpr>(FromExpr)) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< ToTy << (unsigned)isObjectArgument << I + 1
<< (Conv.Bad.Kind == BadConversionSequence::too_few_initializers ? 1
: Conv.Bad.Kind == BadConversionSequence::too_many_initializers
? 2
: 0);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
QualType TempFromTy = FromTy.getNonReferenceType();
if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
TempFromTy = PTy->getPointeeType();
if (TempFromTy->isIncompleteType()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< ToTy << (unsigned)isObjectArgument << I + 1
<< (unsigned)(Cand->Fix.Kind);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
unsigned BaseToDerivedConversion = 0;
if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) {
if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) {
if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
FromPtrTy->getPointeeType()) &&
!FromPtrTy->getPointeeType()->isIncompleteType() &&
!ToPtrTy->getPointeeType()->isIncompleteType() &&
S.IsDerivedFrom(SourceLocation(), ToPtrTy->getPointeeType(),
FromPtrTy->getPointeeType()))
BaseToDerivedConversion = 1;
}
} else if (const ObjCObjectPointerType *FromPtrTy
= FromTy->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *ToPtrTy
= ToTy->getAs<ObjCObjectPointerType>())
if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl())
if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl())
if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs(
FromPtrTy->getPointeeType()) &&
FromIface->isSuperClassOf(ToIface))
BaseToDerivedConversion = 2;
} else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) {
if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) &&
!FromTy->isIncompleteType() &&
!ToRefTy->getPointeeType()->isIncompleteType() &&
S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) {
BaseToDerivedConversion = 3;
}
}
if (BaseToDerivedConversion) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< (BaseToDerivedConversion - 1) << FromTy << ToTy << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
if (isa<ObjCObjectPointerType>(CFromTy) &&
isa<PointerType>(CToTy)) {
Qualifiers FromQs = CFromTy.getQualifiers();
Qualifiers ToQs = CToTy.getQualifiers();
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
<< FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned)isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
}
if (TakingCandidateAddress &&
!checkAddressOfCandidateIsAvailable(S, Cand->Function))
return;
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
FDiag << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy
<< ToTy << (unsigned)isObjectArgument << I + 1
<< (unsigned)(Cand->Fix.Kind);
for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(),
HE = Cand->Fix.Hints.end(); HI != HE; ++HI)
FDiag << *HI;
S.Diag(Fn->getLocation(), FDiag);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
}
static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
unsigned MinParams = Fn->getMinRequiredArguments();
if (Fn->isInvalidDecl() &&
Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
return true;
if (NumArgs < MinParams) {
assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
(Cand->FailureKind == ovl_fail_bad_deduction &&
Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
} else {
assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
(Cand->FailureKind == ovl_fail_bad_deduction &&
Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
}
return false;
}
static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
unsigned NumFormalArgs) {
assert(isa<FunctionDecl>(D) &&
"The templated declaration should at least be a function"
" when diagnosing bad template argument deduction due to too many"
" or too few arguments");
FunctionDecl *Fn = cast<FunctionDecl>(D);
const auto *FnTy = Fn->getType()->castAs<FunctionProtoType>();
unsigned MinParams = Fn->getMinRequiredArguments();
unsigned mode, modeCount;
if (NumFormalArgs < MinParams) {
if (MinParams != FnTy->getNumParams() || FnTy->isVariadic() ||
FnTy->isTemplateVariadic())
mode = 0; else
mode = 2; modeCount = MinParams;
} else {
if (MinParams != FnTy->getNumParams())
mode = 1; else
mode = 2; modeCount = FnTy->getNumParams();
}
std::string Description;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Found, Fn, CRK_None, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
<< Description << mode << Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second
<< Description << mode << modeCount << NumFormalArgs;
MaybeEmitInheritedConstructorNote(S, Found);
}
static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
unsigned NumFormalArgs) {
if (!CheckArityMismatch(S, Cand, NumFormalArgs))
DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs);
}
static TemplateDecl *getDescribedTemplate(Decl *Templated) {
if (TemplateDecl *TD = Templated->getDescribedTemplate())
return TD;
llvm_unreachable("Unsupported: Getting the described template declaration"
" for bad deduction diagnosis");
}
static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
DeductionFailureInfo &DeductionFailure,
unsigned NumArgs,
bool TakingCandidateAddress) {
TemplateParameter Param = DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
switch (DeductionFailure.Result) {
case Sema::TDK_Success:
llvm_unreachable("TDK_success while diagnosing bad deduction");
case Sema::TDK_Incomplete: {
assert(ParamD && "no parameter found for incomplete deduction result");
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_incomplete_deduction)
<< ParamD->getDeclName();
MaybeEmitInheritedConstructorNote(S, Found);
return;
}
case Sema::TDK_IncompletePack: {
assert(ParamD && "no parameter found for incomplete deduction result");
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_incomplete_deduction_pack)
<< ParamD->getDeclName()
<< (DeductionFailure.getFirstArg()->pack_size() + 1)
<< *DeductionFailure.getFirstArg();
MaybeEmitInheritedConstructorNote(S, Found);
return;
}
case Sema::TDK_Underqualified: {
assert(ParamD && "no parameter found for bad qualifiers deduction result");
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
QualType Param = DeductionFailure.getFirstArg()->getAsType();
QualifierCollector Qs;
Qs.strip(Param);
QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl());
assert(S.Context.hasSameType(Param, NonCanonParam));
QualType Arg = DeductionFailure.getSecondArg()->getAsType();
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified)
<< ParamD->getDeclName() << Arg << NonCanonParam;
MaybeEmitInheritedConstructorNote(S, Found);
return;
}
case Sema::TDK_Inconsistent: {
assert(ParamD && "no parameter found for inconsistent deduction result");
int which = 0;
if (isa<TemplateTypeParmDecl>(ParamD))
which = 0;
else if (isa<NonTypeTemplateParmDecl>(ParamD)) {
QualType T1 =
DeductionFailure.getFirstArg()->getNonTypeTemplateArgumentType();
QualType T2 =
DeductionFailure.getSecondArg()->getNonTypeTemplateArgumentType();
if (!T1.isNull() && !T2.isNull() && !S.Context.hasSameType(T1, T2)) {
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_inconsistent_deduction_types)
<< ParamD->getDeclName() << *DeductionFailure.getFirstArg() << T1
<< *DeductionFailure.getSecondArg() << T2;
MaybeEmitInheritedConstructorNote(S, Found);
return;
}
which = 1;
} else {
which = 2;
}
if (DeductionFailure.getFirstArg()->getKind() == TemplateArgument::Pack &&
DeductionFailure.getSecondArg()->getKind() == TemplateArgument::Pack &&
DeductionFailure.getFirstArg()->pack_size() !=
DeductionFailure.getSecondArg()->pack_size()) {
which = 3;
}
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_inconsistent_deduction)
<< which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
<< *DeductionFailure.getSecondArg();
MaybeEmitInheritedConstructorNote(S, Found);
return;
}
case Sema::TDK_InvalidExplicitArguments:
assert(ParamD && "no parameter found for invalid explicit arguments");
if (ParamD->getDeclName())
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
<< ParamD->getDeclName();
else {
int index = 0;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
index = TTP->getIndex();
else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(ParamD))
index = NTTP->getIndex();
else
index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
<< (index + 1);
}
MaybeEmitInheritedConstructorNote(S, Found);
return;
case Sema::TDK_ConstraintsNotSatisfied: {
SmallString<128> TemplateArgString;
TemplateArgumentList *Args = DeductionFailure.getTemplateArgumentList();
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
if (TemplateArgString.size() == 1)
TemplateArgString.clear();
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_unsatisfied_constraints)
<< TemplateArgString;
S.DiagnoseUnsatisfiedConstraint(
static_cast<CNSInfo*>(DeductionFailure.Data)->Satisfaction);
return;
}
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Found, Templated, NumArgs);
return;
case Sema::TDK_InstantiationDepth:
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_instantiation_depth);
MaybeEmitInheritedConstructorNote(S, Found);
return;
case Sema::TDK_SubstitutionFailure: {
SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
DeductionFailure.getTemplateArgumentList()) {
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
if (TemplateArgString.size() == 1)
TemplateArgString.clear();
}
PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic();
if (PDiag && PDiag->second.getDiagID() ==
diag::err_typename_nested_not_found_enable_if) {
S.Diag(PDiag->first, diag::note_ovl_candidate_disabled_by_enable_if)
<< "'enable_if'" << TemplateArgString;
return;
}
if (PDiag && PDiag->second.getDiagID() ==
diag::err_typename_nested_not_found_requirement) {
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_disabled_by_requirement)
<< PDiag->second.getStringArg(0) << TemplateArgString;
return;
}
SmallString<128> SFINAEArgString;
SourceRange R;
if (PDiag) {
SFINAEArgString = ": ";
R = SourceRange(PDiag->first, PDiag->first);
PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
}
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_substitution_failure)
<< TemplateArgString << SFINAEArgString << R;
MaybeEmitInheritedConstructorNote(S, Found);
return;
}
case Sema::TDK_DeducedMismatch:
case Sema::TDK_DeducedMismatchNested: {
SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
DeductionFailure.getTemplateArgumentList()) {
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
if (TemplateArgString.size() == 1)
TemplateArgString.clear();
}
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
<< (*DeductionFailure.getCallArgIndex() + 1)
<< *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg()
<< TemplateArgString
<< (DeductionFailure.Result == Sema::TDK_DeducedMismatchNested);
break;
}
case Sema::TDK_NonDeducedMismatch: {
TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
TemplateArgument SecondTA = *DeductionFailure.getSecondArg();
if (FirstTA.getKind() == TemplateArgument::Template &&
SecondTA.getKind() == TemplateArgument::Template) {
TemplateName FirstTN = FirstTA.getAsTemplate();
TemplateName SecondTN = SecondTA.getAsTemplate();
if (FirstTN.getKind() == TemplateName::Template &&
SecondTN.getKind() == TemplateName::Template) {
if (FirstTN.getAsTemplateDecl()->getName() ==
SecondTN.getAsTemplateDecl()->getName()) {
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_non_deduced_mismatch_qualified)
<< FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl();
return;
}
}
}
if (TakingCandidateAddress && isa<FunctionDecl>(Templated) &&
!checkAddressOfCandidateIsAvailable(S, cast<FunctionDecl>(Templated)))
return;
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_non_deduced_mismatch)
<< FirstTA << SecondTA;
return;
}
case Sema::TDK_MiscellaneousDeductionFailure:
S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
MaybeEmitInheritedConstructorNote(S, Found);
return;
case Sema::TDK_CUDATargetMismatch:
S.Diag(Templated->getLocation(),
diag::note_cuda_ovl_candidate_target_mismatch);
return;
}
}
static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
unsigned NumArgs,
bool TakingCandidateAddress) {
unsigned TDK = Cand->DeductionFailure.Result;
if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
if (CheckArityMismatch(S, Cand, NumArgs))
return;
}
DiagnoseBadDeduction(S, Cand->FoundDecl, Cand->Function, Cand->DeductionFailure, NumArgs, TakingCandidateAddress);
}
static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Caller = S.getCurFunctionDecl(true);
FunctionDecl *Callee = Cand->Function;
Sema::CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller),
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee,
Cand->getRewriteKind(), FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
<< FnDesc
<< CalleeTarget << CallerTarget;
CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Callee);
if (Meth != nullptr && Meth->isImplicit()) {
CXXRecordDecl *ParentClass = Meth->getParent();
Sema::CXXSpecialMember CSM;
switch (FnKindPair.first) {
default:
return;
case oc_implicit_default_constructor:
CSM = Sema::CXXDefaultConstructor;
break;
case oc_implicit_copy_constructor:
CSM = Sema::CXXCopyConstructor;
break;
case oc_implicit_move_constructor:
CSM = Sema::CXXMoveConstructor;
break;
case oc_implicit_copy_assignment:
CSM = Sema::CXXCopyAssignment;
break;
case oc_implicit_move_assignment:
CSM = Sema::CXXMoveAssignment;
break;
};
bool ConstRHS = false;
if (Meth->getNumParams()) {
if (const ReferenceType *RT =
Meth->getParamDecl(0)->getType()->getAs<ReferenceType>()) {
ConstRHS = RT->getPointeeType().isConstQualified();
}
}
S.inferCUDATargetForImplicitSpecialMember(ParentClass, CSM, Meth,
ConstRHS,
true);
}
}
static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Callee = Cand->Function;
EnableIfAttr *Attr = static_cast<EnableIfAttr*>(Cand->DeductionFailure.Data);
S.Diag(Callee->getLocation(),
diag::note_ovl_candidate_disabled_by_function_cond_attr)
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
}
static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) {
ExplicitSpecifier ES = ExplicitSpecifier::getFromDecl(Cand->Function);
assert(ES.isExplicit() && "not an explicit candidate");
unsigned Kind;
switch (Cand->Function->getDeclKind()) {
case Decl::Kind::CXXConstructor:
Kind = 0;
break;
case Decl::Kind::CXXConversion:
Kind = 1;
break;
case Decl::Kind::CXXDeductionGuide:
Kind = Cand->Function->isImplicit() ? 0 : 2;
break;
default:
llvm_unreachable("invalid Decl");
}
FunctionDecl *First = Cand->Function->getFirstDecl();
if (FunctionDecl *Pattern = First->getTemplateInstantiationPattern())
First = Pattern->getFirstDecl();
S.Diag(First->getLocation(),
diag::note_ovl_candidate_explicit)
<< Kind << (ES.getExpr() ? 1 : 0)
<< (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange());
}
static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
unsigned NumArgs,
bool TakingCandidateAddress,
LangAS CtorDestAS = LangAS::Default) {
FunctionDecl *Fn = Cand->Function;
if (shouldSkipNotingLambdaConversionDecl(Fn))
return;
if (S.getLangOpts().OpenCL && Fn->isImplicit() &&
Cand->FailureKind != ovl_fail_bad_conversion)
return;
if (Cand->Viable) {
if (Fn->isDeleted()) {
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn,
Cand->getRewriteKind(), FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
<< (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc
<< (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->getRewriteKind());
return;
}
switch (Cand->FailureKind) {
case ovl_fail_too_many_arguments:
case ovl_fail_too_few_arguments:
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
return DiagnoseBadDeduction(S, Cand, NumArgs,
TakingCandidateAddress);
case ovl_fail_illegal_constructor: {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor)
<< (Fn->getPrimaryTemplate() ? 1 : 0);
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
case ovl_fail_object_addrspace_mismatch: {
Qualifiers QualsForPrinting;
QualsForPrinting.setAddressSpace(CtorDestAS);
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_illegal_constructor_adrspace_mismatch)
<< QualsForPrinting;
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
}
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
case ovl_fail_final_conversion_not_exact:
return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->getRewriteKind());
case ovl_fail_bad_conversion: {
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
for (unsigned N = Cand->Conversions.size(); I != N; ++I)
if (Cand->Conversions[I].isBad())
return DiagnoseBadConversion(S, Cand, I, TakingCandidateAddress);
return S.NoteOverloadCandidate(Cand->FoundDecl, Fn, Cand->getRewriteKind());
}
case ovl_fail_bad_target:
return DiagnoseBadTarget(S, Cand);
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
case ovl_fail_explicit:
return DiagnoseFailedExplicitSpec(S, Cand);
case ovl_fail_inhctor_slice:
if (cast<CXXConstructorDecl>(Fn)->isCopyOrMoveConstructor())
return;
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_inherited_constructor_slice)
<< (Fn->getPrimaryTemplate() ? 1 : 0)
<< Fn->getParamDecl(0)->getType()->isRValueReferenceType();
MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
return;
case ovl_fail_addr_not_available: {
bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
(void)Available;
assert(!Available);
break;
}
case ovl_non_default_multiversion_function:
break;
case ovl_fail_constraints_not_satisfied: {
std::string FnDesc;
std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn,
Cand->getRewriteKind(), FnDesc);
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_constraints_not_satisfied)
<< (unsigned)FnKindPair.first << (unsigned)ocs_non_template
<< FnDesc ;
ConstraintSatisfaction Satisfaction;
if (S.CheckFunctionConstraints(Fn, Satisfaction))
break;
S.DiagnoseUnsatisfiedConstraint(Satisfaction);
}
}
}
static void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
if (shouldSkipNotingLambdaConversionDecl(Cand->Surrogate))
return;
QualType FnType = Cand->Surrogate->getConversionType();
bool isLValueReference = false;
bool isRValueReference = false;
bool isPointer = false;
if (const LValueReferenceType *FnTypeRef =
FnType->getAs<LValueReferenceType>()) {
FnType = FnTypeRef->getPointeeType();
isLValueReference = true;
} else if (const RValueReferenceType *FnTypeRef =
FnType->getAs<RValueReferenceType>()) {
FnType = FnTypeRef->getPointeeType();
isRValueReference = true;
}
if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
FnType = FnTypePtr->getPointeeType();
isPointer = true;
}
FnType = QualType(FnType->getAs<FunctionType>(), 0);
if (isPointer) FnType = S.Context.getPointerType(FnType);
if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType);
if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType);
S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
<< FnType;
}
static void NoteBuiltinOperatorCandidate(Sema &S, StringRef Opc,
SourceLocation OpLoc,
OverloadCandidate *Cand) {
assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
std::string TypeStr("operator");
TypeStr += Opc;
TypeStr += "(";
TypeStr += Cand->BuiltinParamTypes[0].getAsString();
if (Cand->Conversions.size() == 1) {
TypeStr += ")";
S.Diag(OpLoc, diag::note_ovl_builtin_candidate) << TypeStr;
} else {
TypeStr += ", ";
TypeStr += Cand->BuiltinParamTypes[1].getAsString();
TypeStr += ")";
S.Diag(OpLoc, diag::note_ovl_builtin_candidate) << TypeStr;
}
}
static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
OverloadCandidate *Cand) {
for (const ImplicitConversionSequence &ICS : Cand->Conversions) {
if (ICS.isBad()) break; if (!ICS.isAmbiguous()) continue;
ICS.DiagnoseAmbiguousConversion(
S, OpLoc, S.PDiag(diag::note_ambiguous_type_conversion));
}
}
static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
if (Cand->Function)
return Cand->Function->getLocation();
if (Cand->IsSurrogate)
return Cand->Surrogate->getLocation();
return SourceLocation();
}
static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
switch ((Sema::TemplateDeductionResult)DFI.Result) {
case Sema::TDK_Success:
case Sema::TDK_NonDependentConversionFailure:
llvm_unreachable("non-deduction failure while diagnosing bad deduction");
case Sema::TDK_Invalid:
case Sema::TDK_Incomplete:
case Sema::TDK_IncompletePack:
return 1;
case Sema::TDK_Underqualified:
case Sema::TDK_Inconsistent:
return 2;
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_DeducedMismatch:
case Sema::TDK_ConstraintsNotSatisfied:
case Sema::TDK_DeducedMismatchNested:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
case Sema::TDK_CUDATargetMismatch:
return 3;
case Sema::TDK_InstantiationDepth:
return 4;
case Sema::TDK_InvalidExplicitArguments:
return 5;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
return 6;
}
llvm_unreachable("Unhandled deduction result");
}
namespace {
struct CompareOverloadCandidatesForDisplay {
Sema &S;
SourceLocation Loc;
size_t NumArgs;
OverloadCandidateSet::CandidateSetKind CSK;
CompareOverloadCandidatesForDisplay(
Sema &S, SourceLocation Loc, size_t NArgs,
OverloadCandidateSet::CandidateSetKind CSK)
: S(S), NumArgs(NArgs), CSK(CSK) {}
OverloadFailureKind EffectiveFailureKind(const OverloadCandidate *C) const {
if (C->FailureKind == ovl_fail_too_many_arguments ||
C->FailureKind == ovl_fail_too_few_arguments)
return static_cast<OverloadFailureKind>(C->FailureKind);
if (C->Function) {
if (NumArgs > C->Function->getNumParams() && !C->Function->isVariadic())
return ovl_fail_too_many_arguments;
if (NumArgs < C->Function->getMinRequiredArguments())
return ovl_fail_too_few_arguments;
}
return static_cast<OverloadFailureKind>(C->FailureKind);
}
bool operator()(const OverloadCandidate *L,
const OverloadCandidate *R) {
if (L == R) return false;
if (L->Viable) {
if (!R->Viable) return true;
if (isBetterOverloadCandidate(S, *L, *R, SourceLocation(), CSK))
return true;
if (isBetterOverloadCandidate(S, *R, *L, SourceLocation(), CSK))
return false;
} else if (R->Viable)
return false;
assert(L->Viable == R->Viable);
if (!L->Viable) {
OverloadFailureKind LFailureKind = EffectiveFailureKind(L);
OverloadFailureKind RFailureKind = EffectiveFailureKind(R);
if (LFailureKind == ovl_fail_too_many_arguments ||
LFailureKind == ovl_fail_too_few_arguments) {
if (RFailureKind == ovl_fail_too_many_arguments ||
RFailureKind == ovl_fail_too_few_arguments) {
int LDist = std::abs((int)L->getNumParams() - (int)NumArgs);
int RDist = std::abs((int)R->getNumParams() - (int)NumArgs);
if (LDist == RDist) {
if (LFailureKind == RFailureKind)
return !L->IsSurrogate && R->IsSurrogate;
return LFailureKind == ovl_fail_too_many_arguments;
}
return LDist < RDist;
}
return false;
}
if (RFailureKind == ovl_fail_too_many_arguments ||
RFailureKind == ovl_fail_too_few_arguments)
return true;
if (LFailureKind == ovl_fail_bad_conversion) {
if (RFailureKind != ovl_fail_bad_conversion)
return true;
unsigned numLFixes = L->Fix.NumConversionsFixed;
unsigned numRFixes = R->Fix.NumConversionsFixed;
numLFixes = (numLFixes == 0) ? UINT_MAX : numLFixes;
numRFixes = (numRFixes == 0) ? UINT_MAX : numRFixes;
if (numLFixes != numRFixes) {
return numLFixes < numRFixes;
}
assert(L->Conversions.size() == R->Conversions.size());
int leftBetter = 0;
unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
for (unsigned E = L->Conversions.size(); I != E; ++I) {
switch (CompareImplicitConversionSequences(S, Loc,
L->Conversions[I],
R->Conversions[I])) {
case ImplicitConversionSequence::Better:
leftBetter++;
break;
case ImplicitConversionSequence::Worse:
leftBetter--;
break;
case ImplicitConversionSequence::Indistinguishable:
break;
}
}
if (leftBetter > 0) return true;
if (leftBetter < 0) return false;
} else if (RFailureKind == ovl_fail_bad_conversion)
return false;
if (LFailureKind == ovl_fail_bad_deduction) {
if (RFailureKind != ovl_fail_bad_deduction)
return true;
if (L->DeductionFailure.Result != R->DeductionFailure.Result)
return RankDeductionFailure(L->DeductionFailure)
< RankDeductionFailure(R->DeductionFailure);
} else if (RFailureKind == ovl_fail_bad_deduction)
return false;
}
SourceLocation LLoc = GetLocationForCandidate(L);
SourceLocation RLoc = GetLocationForCandidate(R);
if (LLoc.isInvalid()) return false;
if (RLoc.isInvalid()) return true;
return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
}
};
}
static void
CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
ArrayRef<Expr *> Args,
OverloadCandidateSet::CandidateSetKind CSK) {
assert(!Cand->Viable);
if (Cand->FailureKind != ovl_fail_bad_conversion)
return;
bool Unfixable = false;
Cand->Fix.setConversionChecker(TryCopyInitialization);
unsigned ConvCount = Cand->Conversions.size();
for (unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); ;
++ConvIdx) {
assert(ConvIdx != ConvCount && "no bad conversion in candidate");
if (Cand->Conversions[ConvIdx].isInitialized() &&
Cand->Conversions[ConvIdx].isBad()) {
Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
break;
}
}
bool SuppressUserConversions = false;
unsigned ConvIdx = 0;
unsigned ArgIdx = 0;
ArrayRef<QualType> ParamTypes;
bool Reversed = Cand->isReversed();
if (Cand->IsSurrogate) {
QualType ConvType
= Cand->Surrogate->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
ParamTypes = ConvType->castAs<FunctionProtoType>()->getParamTypes();
ConvIdx = 1;
} else if (Cand->Function) {
ParamTypes =
Cand->Function->getType()->castAs<FunctionProtoType>()->getParamTypes();
if (isa<CXXMethodDecl>(Cand->Function) &&
!isa<CXXConstructorDecl>(Cand->Function) && !Reversed) {
ConvIdx = 1;
if (CSK == OverloadCandidateSet::CSK_Operator &&
Cand->Function->getDeclName().getCXXOverloadedOperator() != OO_Call &&
Cand->Function->getDeclName().getCXXOverloadedOperator() !=
OO_Subscript)
ArgIdx = 1;
}
} else {
assert(ConvCount <= 3);
ParamTypes = Cand->BuiltinParamTypes;
}
for (unsigned ParamIdx = Reversed ? ParamTypes.size() - 1 : 0;
ConvIdx != ConvCount;
++ConvIdx, ++ArgIdx, ParamIdx += (Reversed ? -1 : 1)) {
assert(ArgIdx < Args.size() && "no argument for this arg conversion");
if (Cand->Conversions[ConvIdx].isInitialized()) {
} else if (ParamIdx < ParamTypes.size()) {
if (ParamTypes[ParamIdx]->isDependentType())
Cand->Conversions[ConvIdx].setAsIdentityConversion(
Args[ArgIdx]->getType());
else {
Cand->Conversions[ConvIdx] =
TryCopyInitialization(S, Args[ArgIdx], ParamTypes[ParamIdx],
SuppressUserConversions,
true,
S.getLangOpts().ObjCAutoRefCount);
if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
}
} else
Cand->Conversions[ConvIdx].setEllipsis();
}
}
SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates(
Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
SourceLocation OpLoc,
llvm::function_ref<bool(OverloadCandidate &)> Filter) {
SmallVector<OverloadCandidate*, 32> Cands;
if (OCD == OCD_AllCandidates) Cands.reserve(size());
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (!Filter(*Cand))
continue;
switch (OCD) {
case OCD_AllCandidates:
if (!Cand->Viable) {
if (!Cand->Function && !Cand->IsSurrogate) {
continue;
}
CompleteNonViableCandidate(S, Cand, Args, Kind);
}
break;
case OCD_ViableCandidates:
if (!Cand->Viable)
continue;
break;
case OCD_AmbiguousCandidates:
if (!Cand->Best)
continue;
break;
}
Cands.push_back(Cand);
}
llvm::stable_sort(
Cands, CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size(), Kind));
return Cands;
}
bool OverloadCandidateSet::shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args,
SourceLocation OpLoc) {
bool DeferHint = false;
if (S.getLangOpts().CUDA && S.getLangOpts().GPUDeferDiag) {
auto WrongSidedCands =
CompleteCandidates(S, OCD_AllCandidates, Args, OpLoc, [](auto &Cand) {
return (Cand.Viable == false &&
Cand.FailureKind == ovl_fail_bad_target) ||
(Cand.Function &&
Cand.Function->template hasAttr<CUDAHostAttr>() &&
Cand.Function->template hasAttr<CUDADeviceAttr>());
});
DeferHint = !WrongSidedCands.empty();
}
return DeferHint;
}
void OverloadCandidateSet::NoteCandidates(
PartialDiagnosticAt PD, Sema &S, OverloadCandidateDisplayKind OCD,
ArrayRef<Expr *> Args, StringRef Opc, SourceLocation OpLoc,
llvm::function_ref<bool(OverloadCandidate &)> Filter) {
auto Cands = CompleteCandidates(S, OCD, Args, OpLoc, Filter);
S.Diag(PD.first, PD.second, shouldDeferDiags(S, Args, OpLoc));
NoteCandidates(S, Args, Cands, Opc, OpLoc);
if (OCD == OCD_AmbiguousCandidates)
MaybeDiagnoseAmbiguousConstraints(S, {begin(), end()});
}
void OverloadCandidateSet::NoteCandidates(Sema &S, ArrayRef<Expr *> Args,
ArrayRef<OverloadCandidate *> Cands,
StringRef Opc, SourceLocation OpLoc) {
bool ReportedAmbiguousConversions = false;
const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
unsigned CandsShown = 0;
auto I = Cands.begin(), E = Cands.end();
for (; I != E; ++I) {
OverloadCandidate *Cand = *I;
if (CandsShown >= S.Diags.getNumOverloadCandidatesToShow() &&
ShowOverloads == Ovl_Best) {
break;
}
++CandsShown;
if (Cand->Function)
NoteFunctionCandidate(S, Cand, Args.size(),
false, DestAS);
else if (Cand->IsSurrogate)
NoteSurrogateCandidate(S, Cand);
else {
assert(Cand->Viable &&
"Non-viable built-in candidates are not added to Cands.");
if (!ReportedAmbiguousConversions) {
NoteAmbiguousUserConversions(S, OpLoc, Cand);
ReportedAmbiguousConversions = true;
}
NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand);
}
}
S.Diags.overloadCandidatesShown(CandsShown);
if (I != E)
S.Diag(OpLoc, diag::note_ovl_too_many_candidates,
shouldDeferDiags(S, Args, OpLoc))
<< int(E - I);
}
static SourceLocation
GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
return Cand->Specialization ? Cand->Specialization->getLocation()
: SourceLocation();
}
namespace {
struct CompareTemplateSpecCandidatesForDisplay {
Sema &S;
CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {}
bool operator()(const TemplateSpecCandidate *L,
const TemplateSpecCandidate *R) {
if (L == R)
return false;
if (L->DeductionFailure.Result != R->DeductionFailure.Result)
return RankDeductionFailure(L->DeductionFailure) <
RankDeductionFailure(R->DeductionFailure);
SourceLocation LLoc = GetLocationForCandidate(L);
SourceLocation RLoc = GetLocationForCandidate(R);
if (LLoc.isInvalid())
return false;
if (RLoc.isInvalid())
return true;
return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
}
};
}
void TemplateSpecCandidate::NoteDeductionFailure(Sema &S,
bool ForTakingAddress) {
DiagnoseBadDeduction(S, FoundDecl, Specialization, DeductionFailure, 0, ForTakingAddress);
}
void TemplateSpecCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
i->DeductionFailure.Destroy();
}
}
void TemplateSpecCandidateSet::clear() {
destroyCandidates();
Candidates.clear();
}
void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
SmallVector<TemplateSpecCandidate *, 32> Cands;
Cands.reserve(size());
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (Cand->Specialization)
Cands.push_back(Cand);
}
llvm::sort(Cands, CompareTemplateSpecCandidatesForDisplay(S));
const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E;
unsigned CandsShown = 0;
for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
TemplateSpecCandidate *Cand = *I;
if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
break;
++CandsShown;
assert(Cand->Specialization &&
"Non-matching built-in candidates are not added to Cands.");
Cand->NoteDeductionFailure(S, ForTakingAddress);
}
if (I != E)
S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I);
}
QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
QualType Ret = PossiblyAFunctionType;
if (const PointerType *ToTypePtr =
PossiblyAFunctionType->getAs<PointerType>())
Ret = ToTypePtr->getPointeeType();
else if (const ReferenceType *ToTypeRef =
PossiblyAFunctionType->getAs<ReferenceType>())
Ret = ToTypeRef->getPointeeType();
else if (const MemberPointerType *MemTypePtr =
PossiblyAFunctionType->getAs<MemberPointerType>())
Ret = MemTypePtr->getPointeeType();
Ret =
Context.getCanonicalType(Ret).getUnqualifiedType();
return Ret;
}
static bool completeFunctionType(Sema &S, FunctionDecl *FD, SourceLocation Loc,
bool Complain = true) {
if (S.getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FD, Loc, Complain))
return true;
auto *FPT = FD->getType()->castAs<FunctionProtoType>();
if (S.getLangOpts().CPlusPlus17 &&
isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
!S.ResolveExceptionSpec(Loc, FPT))
return true;
return false;
}
namespace {
class AddressOfFunctionResolver {
Sema& S;
Expr* SourceExpr;
const QualType& TargetType;
QualType TargetFunctionType;
bool Complain;
ASTContext& Context;
bool TargetTypeIsNonStaticMemberFunction;
bool FoundNonTemplateFunction;
bool StaticMemberFunctionFromBoundPointer;
bool HasComplained;
OverloadExpr::FindResult OvlExprInfo;
OverloadExpr *OvlExpr;
TemplateArgumentListInfo OvlExplicitTemplateArgs;
SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
TemplateSpecCandidateSet FailedCandidates;
public:
AddressOfFunctionResolver(Sema &S, Expr *SourceExpr,
const QualType &TargetType, bool Complain)
: S(S), SourceExpr(SourceExpr), TargetType(TargetType),
Complain(Complain), Context(S.getASTContext()),
TargetTypeIsNonStaticMemberFunction(
!!TargetType->getAs<MemberPointerType>()),
FoundNonTemplateFunction(false),
StaticMemberFunctionFromBoundPointer(false),
HasComplained(false),
OvlExprInfo(OverloadExpr::find(SourceExpr)),
OvlExpr(OvlExprInfo.Expression),
FailedCandidates(OvlExpr->getNameLoc(), true) {
ExtractUnqualifiedFunctionTypeFromTargetType();
if (TargetFunctionType->isFunctionType()) {
if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(OvlExpr))
if (!UME->isImplicitAccess() &&
!S.ResolveSingleFunctionTemplateSpecialization(UME))
StaticMemberFunctionFromBoundPointer = true;
} else if (OvlExpr->hasExplicitTemplateArgs()) {
DeclAccessPair dap;
if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization(
OvlExpr, false, &dap)) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
if (!Method->isStatic()) {
TargetTypeIsNonStaticMemberFunction = true;
if (!OvlExprInfo.HasFormOfMemberPointer)
return;
}
Matches.push_back(std::make_pair(dap, Fn));
}
return;
}
if (OvlExpr->hasExplicitTemplateArgs())
OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
if (FindAllFunctionsThatMatchTargetTypeExactly()) {
if (Matches.size() > 1 && !eliminiateSuboptimalOverloadCandidates()) {
if (FoundNonTemplateFunction)
EliminateAllTemplateMatches();
else
EliminateAllExceptMostSpecializedTemplate();
}
}
if (S.getLangOpts().CUDA && Matches.size() > 1)
EliminateSuboptimalCudaMatches();
}
bool hasComplained() const { return HasComplained; }
private:
bool candidateHasExactlyCorrectType(const FunctionDecl *FD) {
QualType Discard;
return Context.hasSameUnqualifiedType(TargetFunctionType, FD->getType()) ||
S.IsFunctionConversion(FD->getType(), TargetFunctionType, Discard);
}
bool isBetterCandidate(const FunctionDecl *A, const FunctionDecl *B) {
return candidateHasExactlyCorrectType(A) &&
(!candidateHasExactlyCorrectType(B) ||
compareEnableIfAttrs(S, A, B) == Comparison::Better);
}
bool eliminiateSuboptimalOverloadCandidates() {
auto Best = Matches.begin();
for (auto I = Matches.begin()+1, E = Matches.end(); I != E; ++I)
if (isBetterCandidate(I->second, Best->second))
Best = I;
const FunctionDecl *BestFn = Best->second;
auto IsBestOrInferiorToBest = [this, BestFn](
const std::pair<DeclAccessPair, FunctionDecl *> &Pair) {
return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second);
};
if (!llvm::all_of(Matches, IsBestOrInferiorToBest))
return false;
Matches[0] = *Best;
Matches.resize(1);
return true;
}
bool isTargetTypeAFunction() const {
return TargetFunctionType->isFunctionType();
}
void inline ExtractUnqualifiedFunctionTypeFromTargetType() {
TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType);
}
bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate,
const DeclAccessPair& CurAccessFunPair) {
if (CXXMethodDecl *Method
= dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
return false;
}
else if (TargetTypeIsNonStaticMemberFunction)
return false;
FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result
= S.DeduceTemplateArguments(FunctionTemplate,
&OvlExplicitTemplateArgs,
TargetFunctionType, Specialization,
Info, true)) {
FailedCandidates.addCandidate()
.set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
return false;
}
assert(S.isSameOrCompatibleFunctionType(
Context.getCanonicalType(Specialization->getType()),
Context.getCanonicalType(TargetFunctionType)));
if (!S.checkAddressOfFunctionIsAvailable(Specialization))
return false;
Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
return true;
}
bool AddMatchingNonTemplateFunction(NamedDecl* Fn,
const DeclAccessPair& CurAccessFunPair) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
return false;
}
else if (TargetTypeIsNonStaticMemberFunction)
return false;
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
if (S.getLangOpts().CUDA)
if (FunctionDecl *Caller = S.getCurFunctionDecl(true))
if (!Caller->isImplicit() && !S.IsAllowedCUDACall(Caller, FunDecl))
return false;
if (FunDecl->isMultiVersion()) {
const auto *TA = FunDecl->getAttr<TargetAttr>();
if (TA && !TA->isDefaultVersion())
return false;
}
if (completeFunctionType(S, FunDecl, SourceExpr->getBeginLoc(),
Complain)) {
HasComplained |= Complain;
return false;
}
if (!S.checkAddressOfFunctionIsAvailable(FunDecl))
return false;
if (!S.getLangOpts().CPlusPlus ||
candidateHasExactlyCorrectType(FunDecl)) {
Matches.push_back(std::make_pair(
CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
FoundNonTemplateFunction = true;
return true;
}
}
return false;
}
bool FindAllFunctionsThatMatchTargetTypeExactly() {
bool Ret = false;
if (IsInvalidFormOfPointerToMemberFunction())
return false;
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
E = OvlExpr->decls_end();
I != E; ++I) {
NamedDecl *Fn = (*I)->getUnderlyingDecl();
if (FunctionTemplateDecl *FunctionTemplate
= dyn_cast<FunctionTemplateDecl>(Fn)) {
if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair()))
Ret = true;
}
else if (!OvlExpr->hasExplicitTemplateArgs() &&
AddMatchingNonTemplateFunction(Fn, I.getPair()))
Ret = true;
}
assert(Ret || Matches.empty());
return Ret;
}
void EliminateAllExceptMostSpecializedTemplate() {
UnresolvedSet<4> MatchesCopy; for (unsigned I = 0, E = Matches.size(); I != E; ++I)
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
UnresolvedSetIterator Result = S.getMostSpecialized(
MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
SourceExpr->getBeginLoc(), S.PDiag(),
S.PDiag(diag::err_addr_ovl_ambiguous)
<< Matches[0].second->getDeclName(),
S.PDiag(diag::note_ovl_candidate)
<< (unsigned)oc_function << (unsigned)ocs_described_template,
Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
Matches[0].second = cast<FunctionDecl>(*Result);
Matches.resize(1);
} else
HasComplained |= Complain;
}
void EliminateAllTemplateMatches() {
for (unsigned I = 0, N = Matches.size(); I != N; ) {
if (Matches[I].second->getPrimaryTemplate() == nullptr)
++I;
else {
Matches[I] = Matches[--N];
Matches.resize(N);
}
}
}
void EliminateSuboptimalCudaMatches() {
S.EraseUnwantedCUDAMatches(S.getCurFunctionDecl(true),
Matches);
}
public:
void ComplainNoMatchesFound() const {
assert(Matches.empty());
S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_no_viable)
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
if (FailedCandidates.empty())
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
true);
else {
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
IEnd = OvlExpr->decls_end();
I != IEnd; ++I)
if (FunctionDecl *Fun =
dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
if (!functionHasPassObjectSizeParams(Fun))
S.NoteOverloadCandidate(*I, Fun, CRK_None, TargetFunctionType,
true);
FailedCandidates.NoteCandidates(S, OvlExpr->getBeginLoc());
}
}
bool IsInvalidFormOfPointerToMemberFunction() const {
return TargetTypeIsNonStaticMemberFunction &&
!OvlExprInfo.HasFormOfMemberPointer;
}
void ComplainIsInvalidFormOfPointerToMemberFunction() const {
S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
<< TargetType << OvlExpr->getSourceRange();
}
bool IsStaticMemberFunctionFromBoundPointer() const {
return StaticMemberFunctionFromBoundPointer;
}
void ComplainIsStaticMemberFunctionFromBoundPointer() const {
S.Diag(OvlExpr->getBeginLoc(),
diag::err_invalid_form_pointer_member_function)
<< OvlExpr->getSourceRange();
}
void ComplainOfInvalidConversion() const {
S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_not_func_ptrref)
<< OvlExpr->getName() << TargetType;
}
void ComplainMultipleMatchesFound() const {
assert(Matches.size() > 1);
S.Diag(OvlExpr->getBeginLoc(), diag::err_addr_ovl_ambiguous)
<< OvlExpr->getName() << OvlExpr->getSourceRange();
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType,
true);
}
bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); }
int getNumMatches() const { return Matches.size(); }
FunctionDecl* getMatchingFunctionDecl() const {
if (Matches.size() != 1) return nullptr;
return Matches[0].second;
}
const DeclAccessPair* getMatchingFunctionAccessPair() const {
if (Matches.size() != 1) return nullptr;
return &Matches[0].first;
}
};
}
FunctionDecl *
Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
QualType TargetType,
bool Complain,
DeclAccessPair &FoundResult,
bool *pHadMultipleCandidates) {
assert(AddressOfExpr->getType() == Context.OverloadTy);
AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType,
Complain);
int NumMatches = Resolver.getNumMatches();
FunctionDecl *Fn = nullptr;
bool ShouldComplain = Complain && !Resolver.hasComplained();
if (NumMatches == 0 && ShouldComplain) {
if (Resolver.IsInvalidFormOfPointerToMemberFunction())
Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
else
Resolver.ComplainNoMatchesFound();
}
else if (NumMatches > 1 && ShouldComplain)
Resolver.ComplainMultipleMatchesFound();
else if (NumMatches == 1) {
Fn = Resolver.getMatchingFunctionDecl();
assert(Fn);
if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(AddressOfExpr->getExprLoc(), FPT);
FoundResult = *Resolver.getMatchingFunctionAccessPair();
if (Complain) {
if (Resolver.IsStaticMemberFunctionFromBoundPointer())
Resolver.ComplainIsStaticMemberFunctionFromBoundPointer();
else
CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
}
}
if (pHadMultipleCandidates)
*pHadMultipleCandidates = Resolver.hadMultipleCandidates();
return Fn;
}
FunctionDecl *
Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) {
OverloadExpr::FindResult R = OverloadExpr::find(E);
OverloadExpr *Ovl = R.Expression;
bool IsResultAmbiguous = false;
FunctionDecl *Result = nullptr;
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;
};
for (auto I = Ovl->decls_begin(), E = Ovl->decls_end(); I != E; ++I) {
auto *FD = dyn_cast<FunctionDecl>(I->getUnderlyingDecl());
if (!FD)
return nullptr;
if (!checkAddressOfFunctionIsAvailable(FD))
continue;
if (Result) {
Optional<bool> MoreConstrainedThanPrevious = CheckMoreConstrained(FD,
Result);
if (!MoreConstrainedThanPrevious) {
IsResultAmbiguous = true;
AmbiguousDecls.push_back(FD);
continue;
}
if (!*MoreConstrainedThanPrevious)
continue;
}
IsResultAmbiguous = false;
DAP = I.getPair();
Result = FD;
}
if (IsResultAmbiguous)
return nullptr;
if (Result) {
SmallVector<const Expr *, 1> ResultAC;
for (FunctionDecl *Skipped : AmbiguousDecls)
if (!CheckMoreConstrained(Skipped, Result))
return nullptr;
Pair = DAP;
}
return Result;
}
bool Sema::resolveAndFixAddressOfSingleOverloadCandidate(
ExprResult &SrcExpr, bool DoFunctionPointerConverion) {
Expr *E = SrcExpr.get();
assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload");
DeclAccessPair DAP;
FunctionDecl *Found = resolveAddressOfSingleOverloadCandidate(E, DAP);
if (!Found || Found->isCPUDispatchMultiVersion() ||
Found->isCPUSpecificMultiVersion())
return false;
DiagnoseUseOfDecl(Found, E->getExprLoc());
CheckAddressOfMemberAccess(E, DAP);
Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found);
if (DoFunctionPointerConverion && Fixed->getType()->isFunctionType())
SrcExpr = DefaultFunctionArrayConversion(Fixed, false);
else
SrcExpr = Fixed;
return true;
}
FunctionDecl *
Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
bool Complain,
DeclAccessPair *FoundResult) {
if (!ovl->hasExplicitTemplateArgs())
return nullptr;
TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
FunctionDecl *Matched = nullptr;
for (UnresolvedSetIterator I = ovl->decls_begin(),
E = ovl->decls_end(); I != E; ++I) {
FunctionTemplateDecl *FunctionTemplate
= cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
FunctionDecl *Specialization = nullptr;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info,
true)) {
FailedCandidates.addCandidate()
.set(I.getPair(), FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
continue;
}
assert(Specialization && "no specialization and no error?");
if (Matched) {
if (Complain) {
Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous)
<< ovl->getName();
NoteAllOverloadCandidates(ovl);
}
return nullptr;
}
Matched = Specialization;
if (FoundResult) *FoundResult = I.getPair();
}
if (Matched &&
completeFunctionType(*this, Matched, ovl->getExprLoc(), Complain))
return nullptr;
return Matched;
}
bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult &SrcExpr, bool doFunctionPointerConverion,
bool complain, SourceRange OpRangeForComplaining,
QualType DestTypeForComplaining,
unsigned DiagIDForComplaining) {
assert(SrcExpr.get()->getType() == Context.OverloadTy);
OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get());
DeclAccessPair found;
ExprResult SingleFunctionExpression;
if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
ovl.Expression, false, &found)) {
if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) {
SrcExpr = ExprError();
return true;
}
if (!ovl.HasFormOfMemberPointer &&
isa<CXXMethodDecl>(fn) &&
cast<CXXMethodDecl>(fn)->isInstance()) {
if (!complain) return false;
Diag(ovl.Expression->getExprLoc(),
diag::err_bound_member_function)
<< 0 << ovl.Expression->getSourceRange();
SrcExpr = ExprError();
return true;
}
SingleFunctionExpression =
FixOverloadedFunctionReference(SrcExpr.get(), found, fn);
if (doFunctionPointerConverion) {
SingleFunctionExpression =
DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.get());
if (SingleFunctionExpression.isInvalid()) {
SrcExpr = ExprError();
return true;
}
}
}
if (!SingleFunctionExpression.isUsable()) {
if (complain) {
Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
<< ovl.Expression->getName()
<< DestTypeForComplaining
<< OpRangeForComplaining
<< ovl.Expression->getQualifierLoc().getSourceRange();
NoteAllOverloadCandidates(SrcExpr.get());
SrcExpr = ExprError();
return true;
}
return false;
}
SrcExpr = SingleFunctionExpression;
return true;
}
static void AddOverloadedCallCandidate(Sema &S,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading,
bool KnownValid) {
NamedDecl *Callee = FoundDecl.getDecl();
if (isa<UsingShadowDecl>(Callee))
Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl();
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
if (ExplicitTemplateArgs) {
assert(!KnownValid && "Explicit template arguments?");
return;
}
if (!isa<FunctionProtoType>(Func->getType()->getAs<FunctionType>()))
return;
S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet,
false,
PartialOverloading);
return;
}
if (FunctionTemplateDecl *FuncTemplate
= dyn_cast<FunctionTemplateDecl>(Callee)) {
S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,
ExplicitTemplateArgs, Args, CandidateSet,
false,
PartialOverloading);
return;
}
assert(!KnownValid && "unhandled case in overloaded call candidate");
}
void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
#ifndef NDEBUG
if (ULE->requiresADL()) {
for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
E = ULE->decls_end(); I != E; ++I) {
assert(!(*I)->getDeclContext()->isRecord());
assert(isa<UsingShadowDecl>(*I) ||
!(*I)->getDeclContext()->isFunctionOrMethod());
assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate());
}
}
#endif
TemplateArgumentListInfo TABuffer;
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
}
for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
E = ULE->decls_end(); I != E; ++I)
AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args,
CandidateSet, PartialOverloading,
true);
if (ULE->requiresADL())
AddArgumentDependentLookupCandidates(ULE->getName(), ULE->getExprLoc(),
Args, ExplicitTemplateArgs,
CandidateSet, PartialOverloading);
}
void Sema::AddOverloadedCallCandidates(
LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet) {
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, Args,
CandidateSet, false, false);
}
static bool canBeDeclaredInNamespace(const DeclarationName &Name) {
switch (Name.getCXXOverloadedOperator()) {
case OO_New: case OO_Array_New:
case OO_Delete: case OO_Array_Delete:
return false;
default:
return true;
}
}
static bool DiagnoseTwoPhaseLookup(
Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS,
LookupResult &R, OverloadCandidateSet::CandidateSetKind CSK,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
CXXRecordDecl **FoundInClass = nullptr) {
if (!SemaRef.inTemplateInstantiation() || !SS.isEmpty())
return false;
for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) {
if (DC->isTransparentContext())
continue;
SemaRef.LookupQualifiedName(R, DC);
if (!R.empty()) {
R.suppressDiagnostics();
OverloadCandidateSet Candidates(FnLoc, CSK);
SemaRef.AddOverloadedCallCandidates(R, ExplicitTemplateArgs, Args,
Candidates);
OverloadCandidateSet::iterator Best;
OverloadingResult OR =
Candidates.BestViableFunction(SemaRef, FnLoc, Best);
if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
if (FoundInClass) {
*FoundInClass = RD;
if (OR == OR_Success) {
R.clear();
R.addDecl(Best->FoundDecl.getDecl(), Best->FoundDecl.getAccess());
R.resolveKind();
}
}
return false;
}
if (OR != OR_Success) {
return false;
}
Sema::AssociatedNamespaceSet AssociatedNamespaces;
Sema::AssociatedClassSet AssociatedClasses;
SemaRef.FindAssociatedClassesAndNamespaces(FnLoc, Args,
AssociatedNamespaces,
AssociatedClasses);
Sema::AssociatedNamespaceSet SuggestedNamespaces;
if (canBeDeclaredInNamespace(R.getLookupName())) {
DeclContext *Std = SemaRef.getStdNamespace();
for (Sema::AssociatedNamespaceSet::iterator
it = AssociatedNamespaces.begin(),
end = AssociatedNamespaces.end(); it != end; ++it) {
if (Std && Std->Encloses(*it))
continue;
NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it);
if (NS &&
NS->getQualifiedNameAsString().find("__") != std::string::npos)
continue;
SuggestedNamespaces.insert(*it);
}
}
SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup)
<< R.getLookupName();
if (SuggestedNamespaces.empty()) {
SemaRef.Diag(Best->Function->getLocation(),
diag::note_not_found_by_two_phase_lookup)
<< R.getLookupName() << 0;
} else if (SuggestedNamespaces.size() == 1) {
SemaRef.Diag(Best->Function->getLocation(),
diag::note_not_found_by_two_phase_lookup)
<< R.getLookupName() << 1 << *SuggestedNamespaces.begin();
} else {
SemaRef.Diag(Best->Function->getLocation(),
diag::note_not_found_by_two_phase_lookup)
<< R.getLookupName() << 2;
}
return true;
}
R.clear();
}
return false;
}
static bool
DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op,
SourceLocation OpLoc,
ArrayRef<Expr *> Args) {
DeclarationName OpName =
SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName);
return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R,
OverloadCandidateSet::CSK_Operator,
nullptr, Args);
}
namespace {
class BuildRecoveryCallExprRAII {
Sema &SemaRef;
public:
BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S) {
assert(SemaRef.IsBuildingRecoveryCallExpr == false);
SemaRef.IsBuildingRecoveryCallExpr = true;
}
~BuildRecoveryCallExprRAII() {
SemaRef.IsBuildingRecoveryCallExpr = false;
}
};
}
static ExprResult
BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
MutableArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool EmptyLookup, bool AllowTypoCorrection) {
if (SemaRef.IsBuildingRecoveryCallExpr)
return ExprResult();
BuildRecoveryCallExprRAII RCE(SemaRef);
CXXScopeSpec SS;
SS.Adopt(ULE->getQualifierLoc());
SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc();
TemplateArgumentListInfo TABuffer;
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
}
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
CXXRecordDecl *FoundInClass = nullptr;
if (DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
OverloadCandidateSet::CSK_Normal,
ExplicitTemplateArgs, Args, &FoundInClass)) {
} else if (EmptyLookup) {
R.clear();
NoTypoCorrectionCCC NoTypoValidator{};
FunctionCallFilterCCC FunctionCallValidator(SemaRef, Args.size(),
ExplicitTemplateArgs != nullptr,
dyn_cast<MemberExpr>(Fn));
CorrectionCandidateCallback &Validator =
AllowTypoCorrection
? static_cast<CorrectionCandidateCallback &>(FunctionCallValidator)
: static_cast<CorrectionCandidateCallback &>(NoTypoValidator);
if (SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, ExplicitTemplateArgs,
Args))
return ExprError();
} else if (FoundInClass && SemaRef.getLangOpts().MSVCCompat) {
if (SemaRef.DiagnoseDependentMemberLookup(R))
return ExprError();
} else {
return ExprResult();
}
assert(!R.empty() && "lookup results empty despite recovery");
if (R.isAmbiguous()) {
R.suppressDiagnostics();
return ExprError();
}
ExprResult NewFn = ExprError();
if ((*R.begin())->isCXXClassMember())
NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R,
ExplicitTemplateArgs, S);
else if (ExplicitTemplateArgs || TemplateKWLoc.isValid())
NewFn = SemaRef.BuildTemplateIdExpr(SS, TemplateKWLoc, R, false,
ExplicitTemplateArgs);
else
NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false);
if (NewFn.isInvalid())
return ExprError();
return SemaRef.BuildCallExpr( nullptr, NewFn.get(), LParenLoc,
MultiExprArg(Args.data(), Args.size()),
RParenLoc);
}
bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
MultiExprArg Args,
SourceLocation RParenLoc,
OverloadCandidateSet *CandidateSet,
ExprResult *Result) {
#ifndef NDEBUG
if (ULE->requiresADL()) {
assert(!ULE->getQualifier() && "qualified name with ADL");
FunctionDecl *F;
if (ULE->decls_begin() != ULE->decls_end() &&
ULE->decls_begin() + 1 == ULE->decls_end() &&
(F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
F->getBuiltinID() && F->isImplicit())
llvm_unreachable("performing ADL for builtin");
assert(getLangOpts().CPlusPlus && "ADL enabled in C");
}
#endif
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) {
*Result = ExprError();
return true;
}
AddOverloadedCallCandidates(ULE, Args, *CandidateSet);
if (getLangOpts().MSVCCompat &&
CurContext->isDependentContext() && !isSFINAEContext() &&
(isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
OverloadCandidateSet::iterator Best;
if (CandidateSet->empty() ||
CandidateSet->BestViableFunction(*this, Fn->getBeginLoc(), Best) ==
OR_No_Viable_Function) {
CallExpr *CE =
CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_PRValue,
RParenLoc, CurFPFeatureOverrides());
CE->markDependentForPostponedNameLookup();
*Result = CE;
return true;
}
}
if (CandidateSet->empty())
return false;
UnbridgedCasts.restore();
return false;
}
static QualType chooseRecoveryType(OverloadCandidateSet &CS,
OverloadCandidateSet::iterator *Best) {
llvm::Optional<QualType> Result;
auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) {
if (!Candidate.Function)
return;
if (Candidate.Function->isInvalidDecl())
return;
QualType T = Candidate.Function->getReturnType();
if (T.isNull())
return;
if (!Result)
Result = T;
else if (Result != T)
Result = QualType();
};
if (Best && *Best != CS.end())
ConsiderCandidate(**Best);
if (!Result)
for (const auto &C : CS)
if (C.Viable)
ConsiderCandidate(C);
if (!Result)
for (const auto &C : CS)
ConsiderCandidate(C);
if (!Result)
return QualType();
auto Value = *Result;
if (Value.isNull() || Value->isUndeducedType())
return QualType();
return Value;
}
static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
OverloadCandidateSet *CandidateSet,
OverloadCandidateSet::iterator *Best,
OverloadingResult OverloadResult,
bool AllowTypoCorrection) {
switch (OverloadResult) {
case OR_Success: {
FunctionDecl *FDecl = (*Best)->Function;
SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl);
if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()))
return ExprError();
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
ExecConfig, false,
(*Best)->IsADLCandidate);
}
case OR_No_Viable_Function: {
ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
Args, RParenLoc,
CandidateSet->empty(),
AllowTypoCorrection);
if (Recovery.isInvalid() || Recovery.isUsable())
return Recovery;
for (const Expr *Arg : Args) {
if (!Arg->getType()->isFunctionType())
continue;
if (auto *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts())) {
auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
if (FD &&
!SemaRef.checkAddressOfFunctionIsAvailable(FD, true,
Arg->getExprLoc()))
return ExprError();
}
}
CandidateSet->NoteCandidates(
PartialDiagnosticAt(
Fn->getBeginLoc(),
SemaRef.PDiag(diag::err_ovl_no_viable_function_in_call)
<< ULE->getName() << Fn->getSourceRange()),
SemaRef, OCD_AllCandidates, Args);
break;
}
case OR_Ambiguous:
CandidateSet->NoteCandidates(
PartialDiagnosticAt(Fn->getBeginLoc(),
SemaRef.PDiag(diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange()),
SemaRef, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted: {
CandidateSet->NoteCandidates(
PartialDiagnosticAt(Fn->getBeginLoc(),
SemaRef.PDiag(diag::err_ovl_deleted_call)
<< ULE->getName() << Fn->getSourceRange()),
SemaRef, OCD_AllCandidates, Args);
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
ExecConfig, false,
(*Best)->IsADLCandidate);
}
}
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,
OverloadCandidateSet &CS) {
for (auto I = CS.begin(), E = CS.end(); I != E; ++I) {
if (I->Viable &&
!S.checkAddressOfFunctionIsAvailable(I->Function, false)) {
I->Viable = false;
I->FailureKind = ovl_fail_addr_not_available;
}
}
}
ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
bool AllowTypoCorrection,
bool CalleesAddressIsTaken) {
OverloadCandidateSet CandidateSet(Fn->getExprLoc(),
OverloadCandidateSet::CSK_Normal);
ExprResult result;
if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
&result))
return result;
if (CalleesAddressIsTaken)
markUnaddressableCandidatesUnviable(*this, CandidateSet);
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best);
return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, RParenLoc,
ExecConfig, &CandidateSet, &Best,
OverloadResult, AllowTypoCorrection);
}
static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
return Functions.size() > 1 ||
(Functions.size() == 1 &&
isa<FunctionTemplateDecl>((*Functions.begin())->getUnderlyingDecl()));
}
ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
NestedNameSpecifierLoc NNSLoc,
DeclarationNameInfo DNI,
const UnresolvedSetImpl &Fns,
bool PerformADL) {
return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI,
PerformADL, IsOverloaded(Fns),
Fns.begin(), Fns.end());
}
ExprResult
Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
const UnresolvedSetImpl &Fns,
Expr *Input, bool PerformADL) {
OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc);
assert(Op != OO_None && "Invalid opcode for overloaded unary operator");
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
if (checkPlaceholderForOverload(*this, Input))
return ExprError();
Expr *Args[2] = { Input, nullptr };
unsigned NumArgs = 1;
if (Opc == UO_PostInc || Opc == UO_PostDec) {
llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy,
SourceLocation());
NumArgs = 2;
}
ArrayRef<Expr *> ArgsArray(Args, NumArgs);
if (Input->isTypeDependent()) {
if (Fns.empty())
return UnaryOperator::Create(Context, Input, Opc, Context.DependentTy,
VK_PRValue, OK_Ordinary, OpLoc, false,
CurFPFeatureOverrides());
CXXRecordDecl *NamingClass = nullptr; ExprResult Fn = CreateUnresolvedLookupExpr(
NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns);
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray,
Context.DependentTy, VK_PRValue, OpLoc,
CurFPFeatureOverrides());
}
OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator);
AddNonMemberOperatorCandidates(Fns, ArgsArray, CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
if (PerformADL) {
AddArgumentDependentLookupCandidates(OpName, OpLoc, ArgsArray,
nullptr,
CandidateSet);
}
AddBuiltinOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success: {
FunctionDecl *FnDecl = Best->Function;
if (FnDecl) {
Expr *Base = nullptr;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], nullptr, Best->FoundDecl);
ExprResult InputRes =
PerformObjectArgumentInitialization(Input, nullptr,
Best->FoundDecl, Method);
if (InputRes.isInvalid())
return ExprError();
Base = Input = InputRes.get();
} else {
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Input);
if (InputInit.isInvalid())
return ExprError();
Input = InputInit.get();
}
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl,
Base, HadMultipleCandidates,
OpLoc);
if (FnExpr.isInvalid())
return ExprError();
QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
Args[0] = Input;
CallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, Op, FnExpr.get(), ArgsArray, ResultTy, VK, OpLoc,
CurFPFeatureOverrides(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
if (CheckFunctionCall(FnDecl, TheCall,
FnDecl->getType()->castAs<FunctionProtoType>()))
return ExprError();
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), FnDecl);
} else {
ExprResult InputRes = PerformImplicitConversion(
Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing,
CCK_ForBuiltinOverloadedOp);
if (InputRes.isInvalid())
return ExprError();
Input = InputRes.get();
break;
}
}
case OR_No_Viable_Function:
if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, ArgsArray))
return ExprError();
break;
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(OpLoc,
PDiag(diag::err_ovl_ambiguous_oper_unary)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getType() << Input->getSourceRange()),
*this, OCD_AmbiguousCandidates, ArgsArray,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getSourceRange()),
*this, OCD_AllCandidates, ArgsArray, UnaryOperator::getOpcodeStr(Opc),
OpLoc);
return ExprError();
}
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
OverloadedOperatorKind Op,
const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args, bool PerformADL) {
SourceLocation OpLoc = CandidateSet.getLocation();
OverloadedOperatorKind ExtraOp =
CandidateSet.getRewriteInfo().AllowRewrittenCandidates
? getRewrittenOverloadedOperator(Op)
: OO_None;
AddNonMemberOperatorCandidates(Fns, Args, CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
if (CandidateSet.getRewriteInfo().shouldAddReversed(Op))
AddMemberOperatorCandidates(Op, OpLoc, {Args[1], Args[0]}, CandidateSet,
OverloadCandidateParamOrder::Reversed);
if (ExtraOp) {
AddMemberOperatorCandidates(ExtraOp, OpLoc, Args, CandidateSet);
if (CandidateSet.getRewriteInfo().shouldAddReversed(ExtraOp))
AddMemberOperatorCandidates(ExtraOp, OpLoc, {Args[1], Args[0]},
CandidateSet,
OverloadCandidateParamOrder::Reversed);
}
if (Op != OO_Equal && PerformADL) {
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
AddArgumentDependentLookupCandidates(OpName, OpLoc, Args,
nullptr,
CandidateSet);
if (ExtraOp) {
DeclarationName ExtraOpName =
Context.DeclarationNames.getCXXOperatorName(ExtraOp);
AddArgumentDependentLookupCandidates(ExtraOpName, OpLoc, Args,
nullptr,
CandidateSet);
}
}
AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
}
ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
const UnresolvedSetImpl &Fns, Expr *LHS,
Expr *RHS, bool PerformADL,
bool AllowRewrittenCandidates,
FunctionDecl *DefaultedFn) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=nullptr;
if (!getLangOpts().CPlusPlus20)
AllowRewrittenCandidates = false;
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
if (Fns.empty()) {
if (BinaryOperator::isCompoundAssignmentOp(Opc))
return CompoundAssignOperator::Create(
Context, Args[0], Args[1], Opc, Context.DependentTy, VK_LValue,
OK_Ordinary, OpLoc, CurFPFeatureOverrides(), Context.DependentTy,
Context.DependentTy);
return BinaryOperator::Create(
Context, Args[0], Args[1], Opc, Context.DependentTy, VK_PRValue,
OK_Ordinary, OpLoc, CurFPFeatureOverrides());
}
CXXRecordDecl *NamingClass = nullptr; DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
DeclarationNameInfo OpNameInfo(OpName, OpLoc);
ExprResult Fn = CreateUnresolvedLookupExpr(
NamingClass, NestedNameSpecifierLoc(), OpNameInfo, Fns, PerformADL);
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), Args,
Context.DependentTy, VK_PRValue, OpLoc,
CurFPFeatureOverrides());
}
if (checkPlaceholderForOverload(*this, Args[1]))
return ExprError();
assert(Args[0]->getObjectKind() != OK_ObjCProperty);
if (checkPlaceholderForOverload(*this, Args[0]))
return ExprError();
if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType())
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
if (Opc == BO_PtrMemD)
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
OverloadCandidateSet CandidateSet(
OpLoc, OverloadCandidateSet::CSK_Operator,
OverloadCandidateSet::OperatorRewriteInfo(Op, AllowRewrittenCandidates));
if (DefaultedFn)
CandidateSet.exclude(DefaultedFn);
LookupOverloadedBinOp(CandidateSet, Op, Fns, Args, PerformADL);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success: {
FunctionDecl *FnDecl = Best->Function;
bool IsReversed = Best->isReversed();
if (IsReversed)
std::swap(Args[0], Args[1]);
if (FnDecl) {
Expr *Base = nullptr;
OverloadedOperatorKind ChosenOp =
FnDecl->getDeclName().getCXXOverloadedOperator();
if (Best->RewriteKind && ChosenOp == OO_EqualEqual &&
!FnDecl->getReturnType()->isBooleanType()) {
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);
if (!IsExtension)
return ExprError();
}
if (AllowRewrittenCandidates && !IsReversed &&
CandidateSet.getRewriteInfo().isReversible()) {
llvm::SmallVector<FunctionDecl*, 4> AmbiguousWith;
for (OverloadCandidate &Cand : CandidateSet) {
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) {
AmbiguousWith.push_back(Cand.Function);
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);
}
}
}
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl);
ExprResult Arg1 =
PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(0)),
SourceLocation(), Args[1]);
if (Arg1.isInvalid())
return ExprError();
ExprResult Arg0 =
PerformObjectArgumentInitialization(Args[0], nullptr,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
Base = Args[0] = Arg0.getAs<Expr>();
Args[1] = RHS = Arg1.getAs<Expr>();
} else {
ExprResult Arg0 = PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(0)),
SourceLocation(), Args[0]);
if (Arg0.isInvalid())
return ExprError();
ExprResult Arg1 =
PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(1)),
SourceLocation(), Args[1]);
if (Arg1.isInvalid())
return ExprError();
Args[0] = LHS = Arg0.getAs<Expr>();
Args[1] = RHS = Arg1.getAs<Expr>();
}
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
Best->FoundDecl, Base,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, ChosenOp, FnExpr.get(), Args, ResultTy, VK, OpLoc,
CurFPFeatureOverrides(), Best->IsADLCandidate);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
return ExprError();
ArrayRef<const Expr *> ArgsArray(Args, 2);
const Expr *ImplicitThis = nullptr;
if (isa<CXXMethodDecl>(FnDecl)) {
ImplicitThis = ArgsArray[0];
ArgsArray = ArgsArray.slice(1);
}
if (Op == OO_Equal)
DiagnoseSelfMove(Args[0], Args[1], OpLoc);
if (ImplicitThis) {
QualType ThisType = Context.getPointerType(ImplicitThis->getType());
QualType ThisTypeFromDecl = Context.getPointerType(
cast<CXXMethodDecl>(FnDecl)->getThisObjectType());
CheckArgAlignment(OpLoc, FnDecl, "'this'", ThisType,
ThisTypeFromDecl);
}
checkCall(FnDecl, nullptr, ImplicitThis, ArgsArray,
isa<CXXMethodDecl>(FnDecl), OpLoc, TheCall->getSourceRange(),
VariadicDoesNotApply);
ExprResult R = MaybeBindToTemporary(TheCall);
if (R.isInvalid())
return ExprError();
R = CheckForImmediateInvocation(R, FnDecl);
if (R.isInvalid())
return ExprError();
if ((Best->RewriteKind & CRK_DifferentOperator) ||
(Op == OO_Spaceship && IsReversed)) {
if (Op == OO_ExclaimEqual) {
assert(ChosenOp == OO_EqualEqual && "unexpected operator name");
R = CreateBuiltinUnaryOp(OpLoc, UO_LNot, R.get());
} else {
assert(ChosenOp == OO_Spaceship && "unexpected operator name");
llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false);
Expr *ZeroLiteral =
IntegerLiteral::Create(Context, Zero, Context.IntTy, OpLoc);
Sema::CodeSynthesisContext Ctx;
Ctx.Kind = Sema::CodeSynthesisContext::RewritingOperatorAsSpaceship;
Ctx.Entity = FnDecl;
pushCodeSynthesisContext(Ctx);
R = CreateOverloadedBinOp(
OpLoc, Opc, Fns, IsReversed ? ZeroLiteral : R.get(),
IsReversed ? R.get() : ZeroLiteral, PerformADL,
false);
popCodeSynthesisContext();
}
if (R.isInvalid())
return ExprError();
} else {
assert(ChosenOp == Op && "unexpected operator name");
}
if (Best->RewriteKind != CRK_None)
R = new (Context) CXXRewrittenBinaryOperator(R.get(), IsReversed);
return R;
} else {
ExprResult ArgsRes0 = PerformImplicitConversion(
Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
ExprResult ArgsRes1 = PerformImplicitConversion(
Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
break;
}
}
case OR_No_Viable_Function: {
if (Opc == BO_Comma)
break;
if (DefaultedFn && Opc == BO_Cmp) {
ExprResult E = BuildSynthesizedThreeWayComparison(OpLoc, Fns, Args[0],
Args[1], DefaultedFn);
if (E.isInvalid() || E.isUsable())
return E;
}
ExprResult Result = ExprError();
StringRef OpcStr = BinaryOperator::getOpcodeStr(Opc);
auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates,
Args, OpLoc);
DeferDiagsRAII DDR(*this,
CandidateSet.shouldDeferDiags(*this, Args, OpLoc));
if (Args[0]->getType()->isRecordType() &&
Opc >= BO_Assign && Opc <= BO_OrAssign) {
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
if (Args[0]->getType()->isIncompleteType()) {
Diag(OpLoc, diag::note_assign_lhs_incomplete)
<< Args[0]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
}
} else {
if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args))
return ExprError();
Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
assert(Result.isInvalid() &&
"C++ binary operator overloading is missing candidates!");
CandidateSet.NoteCandidates(*this, Args, Cands, OpcStr, OpLoc);
return Result;
}
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_binary)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getType()
<< Args[1]->getType()
<< Args[0]->getSourceRange()
<< Args[1]->getSourceRange()),
*this, OCD_AmbiguousCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
OpLoc);
return ExprError();
case OR_Deleted:
if (isImplicitlyDeleted(Best->Function)) {
FunctionDecl *DeletedFD = Best->Function;
DefaultedFunctionKind DFK = getDefaultedFunctionKind(DeletedFD);
if (DFK.isSpecialMember()) {
Diag(OpLoc, diag::err_ovl_deleted_special_oper)
<< Args[0]->getType() << DFK.asSpecialMember();
} else {
assert(DFK.isComparison());
Diag(OpLoc, diag::err_ovl_deleted_comparison)
<< Args[0]->getType() << DeletedFD;
}
NoteDeletedFunction(DeletedFD);
return ExprError();
}
CandidateSet.NoteCandidates(
PartialDiagnosticAt(
OpLoc, PDiag(diag::err_ovl_deleted_oper)
<< getOperatorSpelling(Best->Function->getDeclName()
.getCXXOverloadedOperator())
<< Args[0]->getSourceRange()
<< Args[1]->getSourceRange()),
*this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc),
OpLoc);
return ExprError();
}
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
ExprResult Sema::BuildSynthesizedThreeWayComparison(
SourceLocation OpLoc, const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS,
FunctionDecl *DefaultedFn) {
const ComparisonCategoryInfo *Info =
Context.CompCategories.lookupInfoForType(DefaultedFn->getReturnType());
if (!Info)
return ExprResult((Expr*)nullptr);
assert(LHS->isGLValue() && RHS->isGLValue() &&
"cannot use prvalue expressions more than once");
Expr *OrigLHS = LHS;
Expr *OrigRHS = RHS;
LHS = new (Context)
OpaqueValueExpr(LHS->getExprLoc(), LHS->getType(), LHS->getValueKind(),
LHS->getObjectKind(), LHS);
RHS = new (Context)
OpaqueValueExpr(RHS->getExprLoc(), RHS->getType(), RHS->getValueKind(),
RHS->getObjectKind(), RHS);
ExprResult Eq = CreateOverloadedBinOp(OpLoc, BO_EQ, Fns, LHS, RHS, true, true,
DefaultedFn);
if (Eq.isInvalid())
return ExprError();
ExprResult Less = CreateOverloadedBinOp(OpLoc, BO_LT, Fns, LHS, RHS, true,
true, DefaultedFn);
if (Less.isInvalid())
return ExprError();
ExprResult Greater;
if (Info->isPartial()) {
Greater = CreateOverloadedBinOp(OpLoc, BO_LT, Fns, RHS, LHS, true, true,
DefaultedFn);
if (Greater.isInvalid())
return ExprError();
}
struct Comparison {
ExprResult Cmp;
ComparisonCategoryResult Result;
} Comparisons[4] =
{ {Eq, Info->isStrong() ? ComparisonCategoryResult::Equal
: ComparisonCategoryResult::Equivalent},
{Less, ComparisonCategoryResult::Less},
{Greater, ComparisonCategoryResult::Greater},
{ExprResult(), ComparisonCategoryResult::Unordered},
};
int I = Info->isPartial() ? 3 : 2;
ExprResult Result;
for (; I >= 0; --I) {
auto *VI = Info->lookupValueInfo(Comparisons[I].Result);
if (!VI)
return ExprResult((Expr*)nullptr);
ExprResult ThisResult =
BuildDeclarationNameExpr(CXXScopeSpec(), DeclarationNameInfo(), VI->VD);
if (ThisResult.isInvalid())
return ExprError();
if (Result.get()) {
Result = ActOnConditionalOp(OpLoc, OpLoc, Comparisons[I].Cmp.get(),
ThisResult.get(), Result.get());
if (Result.isInvalid())
return ExprError();
} else {
Result = ThisResult;
}
}
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);
}
static bool PrepareArgumentsForCallToObjectOfClassType(
Sema &S, SmallVectorImpl<Expr *> &MethodArgs, CXXMethodDecl *Method,
MultiExprArg Args, SourceLocation LParenLoc) {
const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
unsigned NumParams = Proto->getNumParams();
unsigned NumArgsSlots =
MethodArgs.size() + std::max<unsigned>(Args.size(), NumParams);
MethodArgs.reserve(MethodArgs.size() + NumArgsSlots);
bool IsError = false;
for (unsigned i = 0; i != NumParams; i++) {
Expr *Arg;
if (i < Args.size()) {
Arg = Args[i];
ExprResult InputInit =
S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
S.Context, Method->getParamDecl(i)),
SourceLocation(), Arg);
IsError |= InputInit.isInvalid();
Arg = InputInit.getAs<Expr>();
} else {
ExprResult DefArg =
S.BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
if (DefArg.isInvalid()) {
IsError = true;
break;
}
Arg = DefArg.getAs<Expr>();
}
MethodArgs.push_back(Arg);
}
return IsError;
}
ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
SourceLocation RLoc,
Expr *Base,
MultiExprArg ArgExpr) {
SmallVector<Expr *, 2> Args;
Args.push_back(Base);
for (auto e : ArgExpr) {
Args.push_back(e);
}
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
SourceRange Range = ArgExpr.empty()
? SourceRange{}
: SourceRange(ArgExpr.front()->getBeginLoc(),
ArgExpr.back()->getEndLoc());
if (Expr::hasAnyTypeDependentArguments(Args)) {
CXXRecordDecl *NamingClass = nullptr; DeclarationNameInfo OpNameInfo(OpName, LLoc);
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
ExprResult Fn = CreateUnresolvedLookupExpr(
NamingClass, NestedNameSpecifierLoc(), OpNameInfo, UnresolvedSet<0>());
if (Fn.isInvalid())
return ExprError();
return CXXOperatorCallExpr::Create(Context, OO_Subscript, Fn.get(), Args,
Context.DependentTy, VK_PRValue, RLoc,
CurFPFeatureOverrides());
}
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) {
return ExprError();
}
OverloadCandidateSet CandidateSet(LLoc, OverloadCandidateSet::CSK_Operator);
AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, CandidateSet);
if (Args.size() == 2)
AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, CandidateSet);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) {
case OR_Success: {
FunctionDecl *FnDecl = Best->Function;
if (FnDecl) {
CheckMemberOperatorAccess(LLoc, Args[0], ArgExpr, Best->FoundDecl);
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
SmallVector<Expr *, 2> MethodArgs;
ExprResult Arg0 = PerformObjectArgumentInitialization(
Args[0], nullptr, Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
MethodArgs.push_back(Arg0.get());
bool IsError = PrepareArgumentsForCallToObjectOfClassType(
*this, MethodArgs, Method, ArgExpr, LLoc);
if (IsError)
return ExprError();
DeclarationNameInfo OpLocInfo(OpName, LLoc);
OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
ExprResult FnExpr = CreateFunctionRefExpr(
*this, FnDecl, Best->FoundDecl, Base, HadMultipleCandidates,
OpLocInfo.getLoc(), OpLocInfo.getInfo());
if (FnExpr.isInvalid())
return ExprError();
QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK, RLoc,
CurFPFeatureOverrides());
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
if (CheckFunctionCall(Method, TheCall,
Method->getType()->castAs<FunctionProtoType>()))
return ExprError();
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall),
FnDecl);
} else {
ExprResult ArgsRes0 = PerformImplicitConversion(
Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0],
AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.get();
ExprResult ArgsRes1 = PerformImplicitConversion(
Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1],
AA_Passing, CCK_ForBuiltinOverloadedOp);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.get();
break;
}
}
case OR_No_Viable_Function: {
PartialDiagnostic PD =
CandidateSet.empty()
? (PDiag(diag::err_ovl_no_oper)
<< Args[0]->getType() << 0
<< Args[0]->getSourceRange() << Range)
: (PDiag(diag::err_ovl_no_viable_subscript)
<< Args[0]->getType() << Args[0]->getSourceRange() << Range);
CandidateSet.NoteCandidates(PartialDiagnosticAt(LLoc, PD), *this,
OCD_AllCandidates, ArgExpr, "[]", LLoc);
return ExprError();
}
case OR_Ambiguous:
if (Args.size() == 2) {
CandidateSet.NoteCandidates(
PartialDiagnosticAt(
LLoc, PDiag(diag::err_ovl_ambiguous_oper_binary)
<< "[]" << Args[0]->getType() << Args[1]->getType()
<< Args[0]->getSourceRange() << Range),
*this, OCD_AmbiguousCandidates, Args, "[]", LLoc);
} else {
CandidateSet.NoteCandidates(
PartialDiagnosticAt(LLoc,
PDiag(diag::err_ovl_ambiguous_subscript_call)
<< Args[0]->getType()
<< Args[0]->getSourceRange() << Range),
*this, OCD_AmbiguousCandidates, Args, "[]", LLoc);
}
return ExprError();
case OR_Deleted:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(LLoc, PDiag(diag::err_ovl_deleted_oper)
<< "[]" << Args[0]->getSourceRange()
<< Range),
*this, OCD_AllCandidates, Args, "[]", LLoc);
return ExprError();
}
return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc);
}
ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig, bool IsExecConfig,
bool AllowRecovery) {
assert(MemExprE->getType() == Context.BoundMemberTy ||
MemExprE->getType() == Context.OverloadTy);
Expr *NakedMemExpr = MemExprE->IgnoreParens();
if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) {
assert(op->getType() == Context.BoundMemberTy);
assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI);
QualType fnType =
op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType();
const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
QualType resultType = proto->getCallResultType(Context);
ExprValueKind valueKind = Expr::getValueKindForType(proto->getReturnType());
Qualifiers funcQuals = proto->getMethodQuals();
QualType objectType = op->getLHS()->getType();
if (op->getOpcode() == BO_PtrMemI)
objectType = objectType->castAs<PointerType>()->getPointeeType();
Qualifiers objectQuals = objectType.getQualifiers();
Qualifiers difference = objectQuals - funcQuals;
difference.removeObjCGCAttr();
difference.removeAddressSpace();
if (difference) {
std::string qualsString = difference.getAsString();
Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
<< fnType.getUnqualifiedType()
<< qualsString
<< (qualsString.find(' ') == std::string::npos ? 1 : 2);
}
CXXMemberCallExpr *call = CXXMemberCallExpr::Create(
Context, MemExprE, Args, resultType, valueKind, RParenLoc,
CurFPFeatureOverrides(), proto->getNumParams());
if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(),
call, nullptr))
return ExprError();
if (ConvertArgumentsForCall(call, op, nullptr, proto, Args, RParenLoc))
return ExprError();
if (CheckOtherCall(call, proto))
return ExprError();
return MaybeBindToTemporary(call);
}
auto BuildRecoveryExpr = [&](QualType Type) {
if (!AllowRecovery)
return ExprError();
std::vector<Expr *> SubExprs = {MemExprE};
llvm::append_range(SubExprs, Args);
return CreateRecoveryExpr(MemExprE->getBeginLoc(), RParenLoc, SubExprs,
Type);
};
if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_PRValue,
RParenLoc, CurFPFeatureOverrides());
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
MemberExpr *MemExpr;
CXXMethodDecl *Method = nullptr;
DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_public);
NestedNameSpecifier *Qualifier = nullptr;
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
FoundDecl = MemExpr->getFoundDecl();
Qualifier = MemExpr->getQualifier();
UnbridgedCasts.restore();
} else {
UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
Qualifier = UnresExpr->getQualifier();
QualType ObjectType = UnresExpr->getBaseType();
Expr::Classification ObjectClassification
= UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue()
: UnresExpr->getBase()->Classify(Context);
OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc(),
OverloadCandidateSet::CSK_Normal);
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UnresExpr->hasExplicitTemplateArgs()) {
UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
}
for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
E = UnresExpr->decls_end(); I != E; ++I) {
NamedDecl *Func = *I;
CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(Func->getDeclContext());
if (isa<UsingShadowDecl>(Func))
Func = cast<UsingShadowDecl>(Func)->getTargetDecl();
if (getLangOpts().MicrosoftExt && isa<CXXConstructorDecl>(Func)) {
AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args,
CandidateSet,
false);
} else if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
if (TemplateArgs)
continue;
AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
ObjectClassification, Args, CandidateSet,
false);
} else {
AddMethodTemplateCandidate(
cast<FunctionTemplateDecl>(Func), I.getPair(), ActingDC,
TemplateArgs, ObjectType, ObjectClassification, Args, CandidateSet,
false);
}
}
DeclarationName DeclName = UnresExpr->getMemberName();
UnbridgedCasts.restore();
OverloadCandidateSet::iterator Best;
bool Succeeded = false;
switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
break;
if (Method != FoundDecl.getDecl() &&
DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
break;
Succeeded = true;
break;
case OR_No_Viable_Function:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(
UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AllCandidates, Args);
break;
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(UnresExpr->getMemberLoc(),
PDiag(diag::err_ovl_deleted_member_call)
<< DeclName << MemExprE->getSourceRange()),
*this, OCD_AllCandidates, Args);
break;
}
if (!Succeeded)
return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best));
MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
if (Method->isStatic()) {
return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, Args, RParenLoc,
ExecConfig, IsExecConfig);
}
MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
}
QualType ResultType = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
assert(Method && "Member call to something that isn't a method?");
const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
CXXMemberCallExpr *TheCall = CXXMemberCallExpr::Create(
Context, MemExprE, Args, ResultType, VK, RParenLoc,
CurFPFeatureOverrides(), Proto->getNumParams());
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
return BuildRecoveryExpr(ResultType);
if (!Method->isStatic()) {
ExprResult ObjectArg =
PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier,
FoundDecl, Method);
if (ObjectArg.isInvalid())
return ExprError();
MemExpr->setBase(ObjectArg.get());
}
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
return BuildRecoveryExpr(ResultType);
DiagnoseSentinelCalls(Method, LParenLoc, Args);
if (CheckFunctionCall(Method, TheCall, Proto))
return ExprError();
if (auto *MemE = dyn_cast<MemberExpr>(NakedMemExpr)) {
if (const EnableIfAttr *Attr =
CheckEnableIf(Method, LParenLoc, Args, true)) {
Diag(MemE->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< Method << Method->getSourceRange();
Diag(Method->getLocation(),
diag::note_ovl_candidate_disabled_by_function_cond_attr)
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
return ExprError();
}
}
if ((isa<CXXConstructorDecl>(CurContext) ||
isa<CXXDestructorDecl>(CurContext)) &&
TheCall->getMethodDecl()->isPure()) {
const CXXMethodDecl *MD = TheCall->getMethodDecl();
if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts()) &&
MemExpr->performsVirtualDispatch(getLangOpts())) {
Diag(MemExpr->getBeginLoc(),
diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
<< MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
<< MD->getParent();
Diag(MD->getBeginLoc(), diag::note_previous_decl) << MD->getDeclName();
if (getLangOpts().AppleKext)
Diag(MemExpr->getBeginLoc(), diag::note_pure_qualified_call_kext)
<< MD->getParent() << MD->getDeclName();
}
}
if (CXXDestructorDecl *DD =
dyn_cast<CXXDestructorDecl>(TheCall->getMethodDecl())) {
bool CallCanBeVirtual = !MemExpr->hasQualifier() || getLangOpts().AppleKext;
CheckVirtualDtorCall(DD, MemExpr->getBeginLoc(), false,
CallCanBeVirtual, true,
MemExpr->getMemberLoc());
}
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall),
TheCall->getMethodDecl());
}
ExprResult
Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc) {
if (checkPlaceholderForOverload(*this, Obj))
return ExprError();
ExprResult Object = Obj;
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
assert(Object.get()->getType()->isRecordType() &&
"Requires object type argument");
OverloadCandidateSet CandidateSet(LParenLoc,
OverloadCandidateSet::CSK_Operator);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
if (RequireCompleteType(LParenLoc, Object.get()->getType(),
diag::err_incomplete_object_call, Object.get()))
return true;
const auto *Record = Object.get()->getType()->castAs<RecordType>();
LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName);
LookupQualifiedName(R, Record->getDecl());
R.suppressDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Object.get()->getType(),
Object.get()->Classify(Context), Args, CandidateSet,
false);
}
const auto &Conversions =
cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
for (auto I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
NamedDecl *D = *I;
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
if (isa<FunctionTemplateDecl>(D))
continue;
CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);
if (!Conv->isExplicit()) {
QualType ConvType = Conv->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
{
AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
Object.get(), Args, CandidateSet);
}
}
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, Object.get()->getBeginLoc(),
Best)) {
case OR_Success:
break;
case OR_No_Viable_Function: {
PartialDiagnostic PD =
CandidateSet.empty()
? (PDiag(diag::err_ovl_no_oper)
<< Object.get()->getType() << 1
<< Object.get()->getSourceRange())
: (PDiag(diag::err_ovl_no_viable_object_call)
<< Object.get()->getType() << Object.get()->getSourceRange());
CandidateSet.NoteCandidates(
PartialDiagnosticAt(Object.get()->getBeginLoc(), PD), *this,
OCD_AllCandidates, Args);
break;
}
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(Object.get()->getBeginLoc(),
PDiag(diag::err_ovl_ambiguous_object_call)
<< Object.get()->getType()
<< Object.get()->getSourceRange()),
*this, OCD_AmbiguousCandidates, Args);
break;
case OR_Deleted:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(Object.get()->getBeginLoc(),
PDiag(diag::err_ovl_deleted_object_call)
<< Object.get()->getType()
<< Object.get()->getSourceRange()),
*this, OCD_AllCandidates, Args);
break;
}
if (Best == CandidateSet.end())
return true;
UnbridgedCasts.restore();
if (Best->Function == nullptr) {
CXXConversionDecl *Conv
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
CheckMemberOperatorAccess(LParenLoc, Object.get(), nullptr,
Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc))
return ExprError();
assert(Conv == Best->FoundDecl.getDecl() &&
"Found Decl & conversion-to-functionptr should be same, right?!");
ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl,
Conv, HadMultipleCandidates);
if (Call.isInvalid())
return ExprError();
Call = ImplicitCastExpr::Create(
Context, Call.get()->getType(), CK_UserDefinedConversion, Call.get(),
nullptr, VK_PRValue, CurFPFeatureOverrides());
return BuildCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
CheckMemberOperatorAccess(LParenLoc, Object.get(), nullptr, Best->FoundDecl);
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
if (Method->isInvalidDecl())
return ExprError();
const auto *Proto = Method->getType()->castAs<FunctionProtoType>();
unsigned NumParams = Proto->getNumParams();
DeclarationNameInfo OpLocInfo(
Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc);
OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc));
ExprResult NewFn = CreateFunctionRefExpr(*this, Method, Best->FoundDecl,
Obj, HadMultipleCandidates,
OpLocInfo.getLoc(),
OpLocInfo.getInfo());
if (NewFn.isInvalid())
return true;
SmallVector<Expr *, 8> MethodArgs;
MethodArgs.reserve(NumParams + 1);
bool IsError = false;
ExprResult ObjRes =
PerformObjectArgumentInitialization(Object.get(), nullptr,
Best->FoundDecl, Method);
if (ObjRes.isInvalid())
IsError = true;
else
Object = ObjRes;
MethodArgs.push_back(Object.get());
IsError |= PrepareArgumentsForCallToObjectOfClassType(
*this, MethodArgs, Method, Args, LParenLoc);
if (Proto->isVariadic()) {
for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
nullptr);
IsError |= Arg.isInvalid();
MethodArgs.push_back(Arg.get());
}
}
if (IsError)
return true;
DiagnoseSentinelCalls(Method, LParenLoc, Args);
QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, VK, RParenLoc,
CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
if (CheckFunctionCall(Method, TheCall, Proto))
return true;
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
}
ExprResult
Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
bool *NoArrowOperatorFound) {
assert(Base->getType()->isRecordType() &&
"left-hand side must have class type");
if (checkPlaceholderForOverload(*this, Base))
return ExprError();
SourceLocation Loc = Base->getExprLoc();
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Arrow);
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Operator);
if (RequireCompleteType(Loc, Base->getType(),
diag::err_typecheck_incomplete_tag, Base))
return ExprError();
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
LookupQualifiedName(R, Base->getType()->castAs<RecordType>()->getDecl());
R.suppressDiagnostics();
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context),
None, CandidateSet, false);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success:
break;
case OR_No_Viable_Function: {
auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, Base);
if (CandidateSet.empty()) {
QualType BaseType = Base->getType();
if (NoArrowOperatorFound) {
*NoArrowOperatorFound = true;
return ExprError();
}
Diag(OpLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << Base->getSourceRange();
if (BaseType->isRecordType() && !BaseType->isPointerType()) {
Diag(OpLoc, diag::note_typecheck_member_reference_suggestion)
<< FixItHint::CreateReplacement(OpLoc, ".");
}
} else
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< "operator->" << Base->getSourceRange();
CandidateSet.NoteCandidates(*this, Base, Cands);
return ExprError();
}
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_unary)
<< "->" << Base->getType()
<< Base->getSourceRange()),
*this, OCD_AmbiguousCandidates, Base);
return ExprError();
case OR_Deleted:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper)
<< "->" << Base->getSourceRange()),
*this, OCD_AllCandidates, Base);
return ExprError();
}
CheckMemberOperatorAccess(OpLoc, Base, nullptr, Best->FoundDecl);
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
ExprResult BaseResult =
PerformObjectArgumentInitialization(Base, nullptr,
Best->FoundDecl, Method);
if (BaseResult.isInvalid())
return ExprError();
Base = BaseResult.get();
ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl,
Base, HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
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, CurFPFeatureOverrides());
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
if (CheckFunctionCall(Method, TheCall,
Method->getType()->castAs<FunctionProtoType>()))
return ExprError();
return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method);
}
ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
DeclarationNameInfo &SuffixInfo,
ArrayRef<Expr*> Args,
SourceLocation LitEndLoc,
TemplateArgumentListInfo *TemplateArgs) {
SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc();
OverloadCandidateSet CandidateSet(UDSuffixLoc,
OverloadCandidateSet::CSK_Normal);
AddNonMemberOperatorCandidates(R.asUnresolvedSet(), Args, CandidateSet,
TemplateArgs);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, UDSuffixLoc, Best)) {
case OR_Success:
case OR_Deleted:
break;
case OR_No_Viable_Function:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(UDSuffixLoc,
PDiag(diag::err_ovl_no_viable_function_in_call)
<< R.getLookupName()),
*this, OCD_AllCandidates, Args);
return ExprError();
case OR_Ambiguous:
CandidateSet.NoteCandidates(
PartialDiagnosticAt(R.getNameLoc(), PDiag(diag::err_ovl_ambiguous_call)
<< R.getLookupName()),
*this, OCD_AmbiguousCandidates, Args);
return ExprError();
}
FunctionDecl *FD = Best->Function;
ExprResult Fn = CreateFunctionRefExpr(*this, FD, Best->FoundDecl,
nullptr, HadMultipleCandidates,
SuffixInfo.getLoc(),
SuffixInfo.getInfo());
if (Fn.isInvalid())
return true;
Expr *ConvArgs[2];
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
ExprResult InputInit = PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context, FD->getParamDecl(ArgIdx)),
SourceLocation(), Args[ArgIdx]);
if (InputInit.isInvalid())
return true;
ConvArgs[ArgIdx] = InputInit.get();
}
QualType ResultTy = FD->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
UserDefinedLiteral *UDL = UserDefinedLiteral::Create(
Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy,
VK, LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides());
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
if (CheckFunctionCall(FD, UDL, nullptr))
return ExprError();
return CheckForImmediateInvocation(MaybeBindToTemporary(UDL), FD);
}
Sema::ForRangeStatus
Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
SourceLocation RangeLoc,
const DeclarationNameInfo &NameInfo,
LookupResult &MemberLookup,
OverloadCandidateSet *CandidateSet,
Expr *Range, ExprResult *CallExpr) {
Scope *S = nullptr;
CandidateSet->clear(OverloadCandidateSet::CSK_Normal);
if (!MemberLookup.empty()) {
ExprResult MemberRef =
BuildMemberReferenceExpr(Range, Range->getType(), Loc,
false, CXXScopeSpec(),
SourceLocation(),
nullptr,
MemberLookup,
nullptr, S);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
return FRS_DiagnosticIssued;
}
*CallExpr = BuildCallExpr(S, MemberRef.get(), Loc, None, Loc, nullptr);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
return FRS_DiagnosticIssued;
}
} else {
ExprResult FnR = CreateUnresolvedLookupExpr(nullptr,
NestedNameSpecifierLoc(),
NameInfo, UnresolvedSet<0>());
if (FnR.isInvalid())
return FRS_DiagnosticIssued;
UnresolvedLookupExpr *Fn = cast<UnresolvedLookupExpr>(FnR.get());
bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, Range, Loc,
CandidateSet, CallExpr);
if (CandidateSet->empty() || CandidateSetError) {
*CallExpr = ExprError();
return FRS_NoViableFunction;
}
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
CandidateSet->BestViableFunction(*this, Fn->getBeginLoc(), Best);
if (OverloadResult == OR_No_Viable_Function) {
*CallExpr = ExprError();
return FRS_NoViableFunction;
}
*CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, Range,
Loc, nullptr, CandidateSet, &Best,
OverloadResult,
false);
if (CallExpr->isInvalid() || OverloadResult != OR_Success) {
*CallExpr = ExprError();
return FRS_DiagnosticIssued;
}
}
return FRS_Success;
}
Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
FunctionDecl *Fn) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
Found, Fn);
if (SubExpr == PE->getSubExpr())
return PE;
return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr);
}
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
Found, Fn);
assert(Context.hasSameType(ICE->getSubExpr()->getType(),
SubExpr->getType()) &&
"Implicit cast type cannot be determined from overload");
assert(ICE->path_empty() && "fixing up hierarchy conversion?");
if (SubExpr == ICE->getSubExpr())
return ICE;
return ImplicitCastExpr::Create(Context, ICE->getType(), ICE->getCastKind(),
SubExpr, nullptr, ICE->getValueKind(),
CurFPFeatureOverrides());
}
if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) {
if (!GSE->isResultDependent()) {
Expr *SubExpr =
FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn);
if (SubExpr == GSE->getResultExpr())
return GSE;
ArrayRef<Expr *> A = GSE->getAssocExprs();
SmallVector<Expr *, 4> AssocExprs(A.begin(), A.end());
unsigned ResultIdx = GSE->getResultIndex();
AssocExprs[ResultIdx] = SubExpr;
return GenericSelectionExpr::Create(
Context, GSE->getGenericLoc(), GSE->getControllingExpr(),
GSE->getAssocTypeSourceInfos(), AssocExprs, GSE->getDefaultLoc(),
GSE->getRParenLoc(), GSE->containsUnexpandedParameterPack(),
ResultIdx);
}
return GSE;
}
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {
assert(UnOp->getOpcode() == UO_AddrOf &&
"Can only take the address of an overloaded function");
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
if (Method->isStatic()) {
} else {
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
Found, Fn);
if (SubExpr == UnOp->getSubExpr())
return UnOp;
assert(isa<DeclRefExpr>(SubExpr)
&& "fixed to something other than a decl ref");
assert(cast<DeclRefExpr>(SubExpr)->getQualifier()
&& "fixed to a member ref with no nested name qualifier");
QualType ClassType
= Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
QualType MemPtrType
= Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
return UnaryOperator::Create(
Context, SubExpr, UO_AddrOf, MemPtrType, VK_PRValue, OK_Ordinary,
UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
Found, Fn);
if (SubExpr == UnOp->getSubExpr())
return UnOp;
return CreateBuiltinUnaryOp(UnOp->getOperatorLoc(), UO_AddrOf, SubExpr)
.get();
}
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
}
QualType Type = Fn->getType();
ExprValueKind ValueKind = getLangOpts().CPlusPlus ? VK_LValue : VK_PRValue;
if (unsigned BID = Fn->getBuiltinID()) {
if (!Context.BuiltinInfo.isDirectlyAddressable(BID)) {
Type = Context.BuiltinFnTy;
ValueKind = VK_PRValue;
}
}
DeclRefExpr *DRE = BuildDeclRefExpr(
Fn, Type, ValueKind, ULE->getNameInfo(), ULE->getQualifierLoc(),
Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs);
DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
return DRE;
}
if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (MemExpr->hasExplicitTemplateArgs()) {
MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
}
Expr *Base;
if (MemExpr->isImplicitAccess()) {
if (cast<CXXMethodDecl>(Fn)->isStatic()) {
DeclRefExpr *DRE = BuildDeclRefExpr(
Fn, Fn->getType(), VK_LValue, MemExpr->getNameInfo(),
MemExpr->getQualifierLoc(), Found.getDecl(),
MemExpr->getTemplateKeywordLoc(), TemplateArgs);
DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
return DRE;
} else {
SourceLocation Loc = MemExpr->getMemberLoc();
if (MemExpr->getQualifier())
Loc = MemExpr->getQualifierLoc().getBeginLoc();
Base =
BuildCXXThisExpr(Loc, MemExpr->getBaseType(), true);
}
} else
Base = MemExpr->getBase();
ExprValueKind valueKind;
QualType type;
if (cast<CXXMethodDecl>(Fn)->isStatic()) {
valueKind = VK_LValue;
type = Fn->getType();
} else {
valueKind = VK_PRValue;
type = Context.BoundMemberTy;
}
return BuildMemberExpr(
Base, MemExpr->isArrow(), MemExpr->getOperatorLoc(),
MemExpr->getQualifierLoc(), MemExpr->getTemplateKeywordLoc(), Fn, Found,
true, MemExpr->getMemberNameInfo(),
type, valueKind, OK_Ordinary, TemplateArgs);
}
llvm_unreachable("Invalid reference to overloaded function");
}
ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
DeclAccessPair Found,
FunctionDecl *Fn) {
return FixOverloadedFunctionReference(E.get(), Found, Fn);
}
bool clang::shouldEnforceArgLimit(bool PartialOverloading,
FunctionDecl *Function) {
if (!PartialOverloading || !Function)
return true;
if (Function->isVariadic())
return false;
if (const auto *Proto =
dyn_cast<FunctionProtoType>(Function->getFunctionType()))
if (Proto->isTemplateVariadic())
return false;
if (auto *Pattern = Function->getTemplateInstantiationPattern())
if (const auto *Proto =
dyn_cast<FunctionProtoType>(Pattern->getFunctionType()))
if (Proto->isTemplateVariadic())
return false;
return true;
}