#include "clang/Sema/Overload.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.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/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include <algorithm>
namespace clang {
using namespace sema;
static ExprResult
CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl,
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(Fn, false, Fn->getType(),
VK_LValue, Loc, LocInfo);
if (HadMultipleCandidates)
DRE->setHadMultipleCandidates(true);
S.MarkDeclRefReferenced(DRE);
ExprResult E = S.Owned(DRE);
E = S.DefaultFunctionArrayConversion(E.take());
if (E.isInvalid())
return ExprError();
return E;
}
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,
bool AllowExplicit,
bool AllowObjCConversionOnExplicit);
static ImplicitConversionSequence::CompareKind
CompareStandardConversionSequences(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
static ImplicitConversionSequence::CompareKind
CompareQualificationConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
static ImplicitConversionSequence::CompareKind
CompareDerivedToBaseConversions(Sema &S,
const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2);
ImplicitConversionCategory
GetConversionCategory(ImplicitConversionKind Kind) {
static const ImplicitConversionCategory
Category[(int)ICK_Num_Conversion_Kinds] = {
ICC_Identity,
ICC_Lvalue_Transformation,
ICC_Lvalue_Transformation,
ICC_Lvalue_Transformation,
ICC_Identity,
ICC_Qualification_Adjustment,
ICC_Promotion,
ICC_Promotion,
ICC_Promotion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion,
ICC_Conversion
};
return Category[(int)Kind];
}
ImplicitConversionRank 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_Complex_Real_Conversion,
ICR_Conversion,
ICR_Conversion,
ICR_Writeback_Conversion
};
return Rank[(int)Kind];
}
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",
"Noreturn adjustment",
"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",
"Vector splat",
"Complex-real conversion",
"Block Pointer conversion",
"Transparent Union Conversion"
"Writeback 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 = 0;
}
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()->isObjCObjectPointerType() ||
getFromType()->isBlockPointerType() ||
getFromType()->isNullPtrType() ||
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(const Expr *Converted) {
while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Converted)) {
switch (ICE->getCastKind()) {
case CK_NoOp:
case CK_IntegralCast:
case CK_IntegralToBoolean:
case CK_IntegralToFloating:
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) const {
assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
QualType FromType = getToType(0);
QualType ToType = getToType(1);
switch (Second) {
case ICK_Floating_Integral:
if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) {
return NK_Type_Narrowing;
} else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) {
llvm::APSInt IntConstantValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
if (Initializer &&
Initializer->isIntegerConstantExpr(IntConstantValue, 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(Converted);
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_Boolean_Conversion: if (!FromType->isIntegralOrUnscopedEnumerationType()) {
return NK_Not_Narrowing;
} case ICK_Integral_Conversion: {
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)) {
llvm::APSInt InitializerValue;
const Expr *Initializer = IgnoreNarrowingConversion(Converted);
if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) {
return NK_Variable_Narrowing;
}
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;
}
}
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 (isStdInitializerListElement())
OS << "Worst std::initializer_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;
};
}
DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
Sema::TemplateDeductionResult TDK,
TemplateDeductionInfo &Info) {
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
Result.Data = 0;
switch (TDK) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
break;
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
Result.Data = Info.Param.getOpaqueValue();
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_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_FailedOverloadResolution:
Result.Data = Info.Expression;
break;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
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_FailedOverloadResolution:
break;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
Data = 0;
break;
case Sema::TDK_SubstitutionFailure:
Data = 0;
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 0;
}
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_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
return TemplateParameter();
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
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_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
return 0;
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return 0;
}
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_FailedOverloadResolution:
return 0;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->FirstArg;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return 0;
}
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_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_FailedOverloadResolution:
return 0;
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->SecondArg;
case Sema::TDK_MiscellaneousDeductionFailure:
break;
}
return 0;
}
Expr *DeductionFailureInfo::getExpr() {
if (static_cast<Sema::TemplateDeductionResult>(Result) ==
Sema::TDK_FailedOverloadResolution)
return static_cast<Expr*>(Data);
return 0;
}
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
i->Conversions[ii].~ImplicitConversionSequence();
if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction)
i->DeductionFailure.Destroy();
}
}
void OverloadCandidateSet::clear() {
destroyCandidates();
NumInlineSequences = 0;
Candidates.clear();
Functions.clear();
}
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 = 0) {
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.take();
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();
}
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;
}
} else if (isa<UsingDecl>(OldD)) {
assert(Old.getLookupKind() == LookupUsingDeclName);
} else if (isa<TagDecl>(OldD)) {
} else if (isa<UnresolvedUsingValueDecl>(OldD)) {
} else {
Match = *I;
return Ovl_NonFunction;
}
}
return Ovl_Overload;
}
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
bool UseUsingDeclRules) {
if (New->isMain())
return false;
if (New->isMSVCRTEntryPoint())
return false;
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
if ((OldTemplate == 0) != (NewTemplate == 0))
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 (!UseUsingDeclRules && NewTemplate &&
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
false, TPL_TemplateMatch) ||
OldType->getReturnType() != NewType->getReturnType()))
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 (!UseUsingDeclRules &&
(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;
}
unsigned OldQuals = OldMethod->getTypeQualifiers();
unsigned NewQuals = NewMethod->getTypeQualifiers();
if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
!isa<CXXConstructorDecl>(NewMethod))
NewQuals |= Qualifiers::Const;
OldQuals &= ~Qualifiers::Restrict;
NewQuals &= ~Qualifiers::Restrict;
if (OldQuals != NewQuals)
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;
}
return false;
}
bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) {
return FD->isUnavailable() && !cast<Decl>(CurContext)->isUnavailable();
}
static ImplicitConversionSequence
TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
bool 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());
OverloadingResult UserDefResult
= IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions,
AllowExplicit, AllowObjCConversionOnExplicit);
if (UserDefResult == OR_Success) {
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(FromCanon, ToCanon))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
}
}
if (SuppressUserConversions && ICS.isUserDefined()) {
ICS.setBad(BadConversionSequence::suppressed_user, From, ToType);
}
} else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) {
ICS.setAmbiguous();
ICS.Ambiguous.setFromType(From->getType());
ICS.Ambiguous.setToType(ToType);
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
if (Cand->Viable)
ICS.Ambiguous.addConversion(Cand->Function);
} else {
ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
}
return ICS;
}
static ImplicitConversionSequence
TryImplicitConversion(Sema &S, Expr *From, QualType ToType,
bool SuppressUserConversions,
bool 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(FromType, ToType))) {
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(FromType);
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = 0;
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,
bool AllowExplicit,
bool InOverloadResolution,
bool CStyle,
bool AllowObjCWritebackConversion) {
return clang::TryImplicitConversion(*this, From, ToType,
SuppressUserConversions, AllowExplicit,
InOverloadResolution, CStyle,
AllowObjCWritebackConversion,
false);
}
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action, bool AllowExplicit) {
ImplicitConversionSequence ICS;
return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS);
}
ExprResult
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action, bool AllowExplicit,
ImplicitConversionSequence& ICS) {
if (checkPlaceholderForOverload(*this, From))
return ExprError();
bool AllowObjCWritebackConversion
= getLangOpts().ObjCAutoRefCount &&
(Action == AA_Passing || Action == AA_Sending);
if (getLangOpts().ObjC1)
CheckObjCBridgeRelatedConversions(From->getLocStart(),
ToType, From->getType(), From);
ICS = clang::TryImplicitConversion(*this, From, ToType,
false,
AllowExplicit,
false,
false,
AllowObjCWritebackConversion,
false);
return PerformImplicitConversion(From, ToType, ICS, Action);
}
bool Sema::IsNoReturnConversion(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.getAs<PointerType>()->getPointeeType();
CanFrom = CanFrom.getAs<PointerType>()->getPointeeType();
} else if (TyClass == Type::BlockPointer) {
CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType();
CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType();
} else if (TyClass == Type::MemberPointer) {
CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType();
CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType();
} else {
return false;
}
TyClass = CanTo->getTypeClass();
if (TyClass != CanFrom->getTypeClass()) return false;
if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto)
return false;
}
const FunctionType *FromFn = cast<FunctionType>(CanFrom);
FunctionType::ExtInfo EInfo = FromFn->getExtInfo();
if (!EInfo.getNoReturn()) return false;
FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(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) {
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->isVectorType() && FromType->isVectorType()) {
if (S.Context.areCompatibleVectorTypes(FromType, ToType) ||
S.isLaxVectorConversion(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 = 0;
if (FromType->isRecordType() || ToType->isRecordType()) {
if (S.getLangOpts().CPlusPlus)
return false;
}
if (FromType == S.Context.OverloadTy) {
DeclAccessPair AccessPair;
if (FunctionDecl *Fn
= S.ResolveAddressOfOverloadedFunction(From, ToType, false,
AccessPair)) {
FromType = Fn->getType();
if (!S.Context.hasSameUnqualifiedType(
S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
QualType resultTy;
if (!S.IsNoReturnConversion(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);
}
assert(S.Context.hasSameType(
FromType,
S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
} 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;
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() ||
FromType->isNullPtrType())) {
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()) {
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
} else if ((FromType->isRealFloatingType() &&
ToType->isIntegralType(S.Context)) ||
(FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isRealFloatingType())) {
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)) {
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 (S.IsNoReturnConversion(FromType, ToType, FromType)) {
SCS.Second = ICK_NoReturn_Adjustment;
} 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 {
SCS.Second = ICK_Identity;
}
SCS.setToType(1, FromType);
QualType CanonFrom;
QualType CanonTo;
bool ObjCLifetimeConversion;
if (S.IsQualificationConversion(FromType, ToType, CStyle,
ObjCLifetimeConversion)) {
SCS.Third = ICK_Qualification;
SCS.QualificationIncludesObjCLifetime = ObjCLifetimeConversion;
FromType = ToType;
CanonFrom = S.Context.getCanonicalType(FromType);
CanonTo = S.Context.getCanonicalType(ToType);
} else {
SCS.Third = ICK_Identity;
CanonFrom = S.Context.getCanonicalType(FromType);
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 false;
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 (RecordDecl::field_iterator it = UD->field_begin(),
itend = UD->field_end();
it != itend; ++it) {
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() ||
(!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(From, Underlying, ToType);
}
if (ToType->isIntegerType() &&
!RequireCompleteType(From->getLocStart(), FromType, 0))
return Context.hasSameUnqualifiedType(ToType,
FromEnumType->getDecl()->getPromotionType());
}
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]);
}
}
}
using llvm::APSInt;
if (From)
if (FieldDecl *MemberDecl = From->getSourceBitField()) {
APSInt BitWidth;
if (FromType->isIntegralType(Context) &&
MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) {
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))
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(0, 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->getAs<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->getAs<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().MicrosoftExt && 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) &&
!RequireCompleteType(From->getLocStart(), FromPointeeType, 0) &&
IsDerivedFrom(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().ObjC1)
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 (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
if ((FromObjCPtr->isObjCQualifiedIdType() ||
ToObjCPtr->isObjCQualifiedIdType()) &&
Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType,
false)) {
ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers);
return true;
}
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->getTypeQuals() != ToFunctionType->getTypeQuals())
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;
}
if (LangOpts.ObjCAutoRefCount &&
!Context.FunctionTypesMatchOnNSConsumedAttrs(FromFunctionType,
ToFunctionType))
return false;
ConvertedType = ToType;
return true;
}
enum {
ft_default,
ft_different_class,
ft_parameter_arity,
ft_parameter_mismatch,
ft_return_type,
ft_qualifer_mismatch
};
void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
QualType FromType, QualType ToType) {
if (FromType.isNull() || ToType.isNull()) {
PDiag << ft_default;
return;
}
if (FromType->isMemberPointerType() && ToType->isMemberPointerType()) {
const MemberPointerType *FromMember = FromType->getAs<MemberPointerType>(),
*ToMember = ToType->getAs<MemberPointerType>();
if (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 = FromType->getAs<FunctionProtoType>(),
*ToFunction = ToType->getAs<FunctionProtoType>();
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;
}
unsigned FromQuals = FromFunction->getTypeQuals(),
ToQuals = ToFunction->getTypeQuals();
if (FromQuals != ToQuals) {
PDiag << ft_qualifer_mismatch << ToQuals << FromQuals;
return;
}
PDiag << ft_default;
}
bool Sema::FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
const FunctionProtoType *NewType,
unsigned *ArgPos) {
for (FunctionProtoType::param_type_iterator O = OldType->param_type_begin(),
N = NewType->param_type_begin(),
E = OldType->param_type_end();
O && (O != E); ++O, ++N) {
if (!Context.hasSameType(O->getUnqualifiedType(),
N->getUnqualifiedType())) {
if (ArgPos)
*ArgPos = O - OldType->param_type_begin();
return false;
}
}
return true;
}
bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
CastKind &Kind,
CXXCastPath& BasePath,
bool IgnoreBaseAccess) {
QualType FromType = From->getType();
bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
Kind = CK_BitCast;
if (!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)) {
if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType,
From->getExprLoc(),
From->getSourceRange(), &BasePath,
IgnoreBaseAccess))
return true;
Kind = CK_DerivedToBase;
}
}
} 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) &&
!RequireCompleteType(From->getLocStart(), ToClass, 0) &&
IsDerivedFrom(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(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;
}
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.UnwrapSimilarPointerTypes(FromType, ToType)) {
UnwrappedAnyPointer = true;
Qualifiers FromQuals = FromType.getQualifiers();
Qualifiers ToQuals = ToType.getQualifiers();
if (FromQuals.getObjCLifetime() != ToQuals.getObjCLifetime() &&
UnwrappedAnyPointer) {
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 (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers()
&& !PreviousToQualsIncludeConst)
return false;
PreviousToQualsIncludeConst
= PreviousToQualsIncludeConst && ToQuals.hasConst();
}
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 FunctionProtoType *CtorType =
Constructor->getType()->getAs<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) {
DeclContext::lookup_result R = S.LookupConstructors(To);
for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
bool Usable = !Constructor->isInvalidDecl() &&
S.isInitListConstructor(Constructor) &&
(AllowExplicit || !Constructor->isExplicit());
if (Usable) {
bool SuppressUserConversions =
isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
0,
From, CandidateSet,
SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
From, CandidateSet,
SuppressUserConversions);
}
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
case OR_Success: {
CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
QualType ThisType = Constructor->getThisType(S.Context);
User.Before.setAsIdentityConversion();
User.HadMultipleCandidates = HadMultipleCandidates;
User.ConversionFunction = Constructor;
User.FoundConversionFunction = Best->FoundDecl;
User.After.setAsIdentityConversion();
User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
return OR_Success;
}
case OR_No_Viable_Function:
return OR_No_Viable_Function;
case OR_Deleted:
return OR_Deleted;
case OR_Ambiguous:
return OR_Ambiguous;
}
llvm_unreachable("Invalid OverloadResult!");
}
static OverloadingResult
IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
bool AllowExplicit,
bool AllowObjCConversionOnExplicit) {
assert(AllowExplicit || !AllowObjCConversionOnExplicit);
bool ConstructorsOnly = false;
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) ||
(From->getType()->getAs<RecordType>() &&
S.IsDerivedFrom(From->getType(), ToType)))
ConstructorsOnly = true;
S.RequireCompleteType(From->getExprLoc(), ToType, 0);
if (ToType->isIncompleteType()) {
} 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);
if (Result != OR_No_Viable_Function)
return Result;
CandidateSet.clear();
Args = InitList->getInits();
NumArgs = InitList->getNumInits();
ListInitializing = true;
}
DeclContext::lookup_result R = S.LookupConstructors(ToRecordDecl);
for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
bool Usable = !Constructor->isInvalidDecl();
if (ListInitializing)
Usable = Usable && (AllowExplicit || !Constructor->isExplicit());
else
Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit);
if (Usable) {
bool SuppressUserConversions = !ConstructorsOnly;
if (SuppressUserConversions && ListInitializing) {
SuppressUserConversions = false;
if (NumArgs == 1) {
SuppressUserConversions = isFirstArgumentCompatibleWithType(
S.Context, Constructor, ToType);
}
}
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
0,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
}
}
}
}
if (ConstructorsOnly || isa<InitListExpr>(From)) {
} else if (S.RequireCompleteType(From->getLocStart(), From->getType(), 0)) {
} else if (const RecordType *FromRecordType
= From->getType()->getAs<RecordType>()) {
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator>
Conversions = FromRecordDecl->getVisibleConversionFunctions();
for (CXXRecordDecl::conversion_iterator
I = Conversions.first, E = Conversions.second; 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 (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
ActingContext, From, ToType,
CandidateSet,
AllowObjCConversionOnExplicit);
else
S.AddConversionCandidate(Conv, FoundDecl, ActingContext,
From, ToType, CandidateSet,
AllowObjCConversionOnExplicit);
}
}
}
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
case OR_Success:
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Best->Function)) {
QualType ThisType = Constructor->getThisType(S.Context);
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->getAs<PointerType>()->getPointeeType());
User.After.setAllToTypes(ToType);
return OR_Success;
}
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 OR_Success;
}
llvm_unreachable("Not a constructor or conversion function?");
case OR_No_Viable_Function:
return OR_No_Viable_Function;
case OR_Deleted:
return OR_Deleted;
case OR_Ambiguous:
return OR_Ambiguous;
}
llvm_unreachable("Invalid OverloadResult!");
}
bool
Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
ImplicitConversionSequence ICS;
OverloadCandidateSet CandidateSet(From->getExprLoc());
OverloadingResult OvResult =
IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
CandidateSet, false, false);
if (OvResult == OR_Ambiguous)
Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition)
<< From->getType() << ToType << From->getSourceRange();
else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) {
if (!RequireCompleteType(From->getLocStart(), ToType,
diag::err_typecheck_nonviable_condition_incomplete,
From->getType(), From->getSourceRange()))
Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
<< From->getType() << From->getSourceRange() << ToType;
} else
return false;
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
return true;
}
static ImplicitConversionSequence::CompareKind
compareConversionFunctions(Sema &S, FunctionDecl *Function1,
FunctionDecl *Function2) {
if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11)
return ImplicitConversionSequence::Indistinguishable;
CXXConversionDecl *Conv1 = dyn_cast_or_null<CXXConversionDecl>(Function1);
if (!Conv1)
return ImplicitConversionSequence::Indistinguishable;
CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2);
if (!Conv2)
return ImplicitConversionSequence::Indistinguishable;
if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) {
bool Block1 = Conv1->getConversionType()->isBlockPointerType();
bool Block2 = Conv2->getConversionType()->isBlockPointerType();
if (Block1 != Block2)
return Block1 ? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
}
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,
const ImplicitConversionSequence& ICS1,
const ImplicitConversionSequence& ICS2)
{
if (S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
hasDeprecatedStringLiteralToCharPtrConversion(ICS1) !=
hasDeprecatedStringLiteralToCharPtrConversion(ICS2))
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.isStandard())
Result = CompareStandardConversionSequences(S,
ICS1.Standard, ICS2.Standard);
else if (ICS1.isUserDefined()) {
if (ICS1.UserDefined.ConversionFunction ==
ICS2.UserDefined.ConversionFunction)
Result = CompareStandardConversionSequences(S,
ICS1.UserDefined.After,
ICS2.UserDefined.After);
else
Result = compareConversionFunctions(S,
ICS1.UserDefined.ConversionFunction,
ICS2.UserDefined.ConversionFunction);
}
if (Result == ImplicitConversionSequence::Indistinguishable &&
!ICS1.isBad()) {
if (ICS1.isStdInitializerListElement() &&
!ICS2.isStdInitializerListElement())
return ImplicitConversionSequence::Better;
if (!ICS1.isStdInitializerListElement() &&
ICS2.isStdInitializerListElement())
return ImplicitConversionSequence::Worse;
}
return Result;
}
static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) {
while (Context.UnwrapSimilarPointerTypes(T1, T2)) {
Qualifiers Quals;
T1 = Context.getUnqualifiedArrayType(T1, Quals);
T2 = Context.getUnqualifiedArrayType(T2, Quals);
}
return Context.hasSameUnqualifiedType(T1, T2);
}
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 (!hasSimilarType(Context, 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);
}
static ImplicitConversionSequence::CompareKind
CompareStandardConversionSequences(Sema &S,
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;
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, 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(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(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 (ImplicitConversionSequence::CompareKind QualCK
= CompareQualificationConversions(S, SCS1, SCS2))
return QualCK;
if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) {
if (isBetterReferenceBindingKind(SCS1, SCS2))
return ImplicitConversionSequence::Better;
else if (isBetterReferenceBindingKind(SCS2, SCS1))
return ImplicitConversionSequence::Worse;
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;
else if (T1.isMoreQualifiedThan(T2))
return ImplicitConversionSequence::Worse;
}
}
if (S.getLangOpts().MSVCCompat && SCS1.Second == ICK_Integral_Conversion &&
SCS2.Second == ICK_Floating_Integral &&
S.Context.getTypeSize(SCS1.getFromType()) ==
S.Context.getTypeSize(SCS1.getToType(2)))
return ImplicitConversionSequence::Better;
return ImplicitConversionSequence::Indistinguishable;
}
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);
Qualifiers T1Quals, T2Quals;
QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals);
QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals);
if (UnqualT1 == UnqualT2)
return ImplicitConversionSequence::Indistinguishable;
if (isa<ArrayType>(T1) && T1Quals)
T1 = S.Context.getQualifiedType(UnqualT1, T1Quals);
if (isa<ArrayType>(T2) && T2Quals)
T2 = S.Context.getQualifiedType(UnqualT2, T2Quals);
ImplicitConversionSequence::CompareKind Result
= ImplicitConversionSequence::Indistinguishable;
if (SCS1.QualificationIncludesObjCLifetime !=
SCS2.QualificationIncludesObjCLifetime) {
Result = SCS1.QualificationIncludesObjCLifetime
? ImplicitConversionSequence::Worse
: ImplicitConversionSequence::Better;
}
while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) {
if (T1.getCVRQualifiers() == T2.getCVRQualifiers())
;
else if (T2.isMoreQualifiedThan(T1)) {
if (Result == ImplicitConversionSequence::Worse)
return ImplicitConversionSequence::Indistinguishable;
Result = ImplicitConversionSequence::Better;
} else if (T1.isMoreQualifiedThan(T2)) {
if (Result == ImplicitConversionSequence::Better)
return ImplicitConversionSequence::Indistinguishable;
Result = ImplicitConversionSequence::Worse;
} else {
return ImplicitConversionSequence::Indistinguishable;
}
if (S.Context.hasSameUnqualifiedType(T1, T2))
break;
}
switch (Result) {
case ImplicitConversionSequence::Better:
if (SCS1.DeprecatedStringLiteralToCharPtr)
Result = ImplicitConversionSequence::Indistinguishable;
break;
case ImplicitConversionSequence::Indistinguishable:
break;
case ImplicitConversionSequence::Worse:
if (SCS2.DeprecatedStringLiteralToCharPtr)
Result = ImplicitConversionSequence::Indistinguishable;
break;
}
return Result;
}
ImplicitConversionSequence::CompareKind
CompareDerivedToBaseConversions(Sema &S,
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->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType ToPointee1
= ToType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType FromPointee2
= FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType ToPointee2
= ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) {
if (S.IsDerivedFrom(ToPointee1, ToPointee2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
return ImplicitConversionSequence::Worse;
}
if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) {
if (S.IsDerivedFrom(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(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))
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 MemberPointerType * FromMemPointer1 =
FromType1->getAs<MemberPointerType>();
const MemberPointerType * ToMemPointer1 =
ToType1->getAs<MemberPointerType>();
const MemberPointerType * FromMemPointer2 =
FromType2->getAs<MemberPointerType>();
const MemberPointerType * ToMemPointer2 =
ToType2->getAs<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(ToPointee1, ToPointee2))
return ImplicitConversionSequence::Worse;
else if (S.IsDerivedFrom(ToPointee2, ToPointee1))
return ImplicitConversionSequence::Better;
}
if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) {
if (S.IsDerivedFrom(FromPointee1, FromPointee2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(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(ToType1, ToType2))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(ToType2, ToType1))
return ImplicitConversionSequence::Worse;
}
if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) &&
S.Context.hasSameUnqualifiedType(ToType1, ToType2)) {
if (S.IsDerivedFrom(FromType2, FromType1))
return ImplicitConversionSequence::Better;
else if (S.IsDerivedFrom(FromType1, FromType2))
return ImplicitConversionSequence::Worse;
}
}
return ImplicitConversionSequence::Indistinguishable;
}
static bool isTypeValid(QualType T) {
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl())
return !Record->isInvalidDecl();
return true;
}
Sema::ReferenceCompareResult
Sema::CompareReferenceRelationship(SourceLocation Loc,
QualType OrigT1, QualType OrigT2,
bool &DerivedToBase,
bool &ObjCConversion,
bool &ObjCLifetimeConversion) {
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);
DerivedToBase = false;
ObjCConversion = false;
ObjCLifetimeConversion = false;
if (UnqualT1 == UnqualT2) {
} else if (!RequireCompleteType(Loc, OrigT2, 0) &&
isTypeValid(UnqualT1) && isTypeValid(UnqualT2) &&
IsDerivedFrom(UnqualT2, UnqualT1))
DerivedToBase = true;
else if (UnqualT1->isObjCObjectOrInterfaceType() &&
UnqualT2->isObjCObjectOrInterfaceType() &&
Context.canBindObjCObjectType(UnqualT1, UnqualT2))
ObjCConversion = true;
else
return Ref_Incompatible;
if (isa<ArrayType>(T1) && T1Quals)
T1 = Context.getQualifiedType(UnqualT1, T1Quals);
if (isa<ArrayType>(T2) && T2Quals)
T2 = Context.getQualifiedType(UnqualT2, T2Quals);
if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime() &&
T1Quals.compatiblyIncludesObjCLifetime(T2Quals)) {
if (isNonTrivialObjCLifetimeConversion(T2Quals, T1Quals))
ObjCLifetimeConversion = true;
T1Quals.removeObjCLifetime();
T2Quals.removeObjCLifetime();
}
if (T1Quals == T2Quals)
return Ref_Compatible;
else if (T1Quals.compatiblyIncludes(T2Quals))
return Ref_Compatible_With_Added_Qualification;
else
return Ref_Related;
}
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.");
CXXRecordDecl *T2RecordDecl
= dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
OverloadCandidateSet CandidateSet(DeclLoc);
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator>
Conversions = T2RecordDecl->getVisibleConversionFunctions();
for (CXXRecordDecl::conversion_iterator
I = Conversions.first, E = Conversions.second; 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 (!AllowExplicit && Conv->isExplicit())
continue;
if (AllowRvalues) {
bool DerivedToBase = false;
bool ObjCConversion = false;
bool ObjCLifetimeConversion = false;
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(),
DerivedToBase, ObjCConversion, ObjCLifetimeConversion) ==
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);
else
S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
DeclType, CandidateSet,
false);
}
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) {
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->Viable)
ICS.Ambiguous.addConversion(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->getAs<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();
bool DerivedToBase = false;
bool ObjCConversion = false;
bool ObjCLifetimeConversion = false;
Expr::Classification InitCategory = Init->Classify(S.Context);
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase,
ObjCConversion, ObjCLifetimeConversion);
if (!isRValRef) {
if (InitCategory.isLValue() &&
RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
: ObjCConversion? ICK_Compatible_Conversion
: ICK_Identity;
ICS.Standard.Third = ICK_Identity;
ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
ICS.Standard.setToType(0, T2);
ICS.Standard.setToType(1, T1);
ICS.Standard.setToType(2, T1);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
ICS.Standard.BindsToRvalue = false;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
ICS.Standard.CopyConstructor = 0;
ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
return ICS;
}
if (!SuppressUserConversions && T2->isRecordType() &&
!S.RequireCompleteType(DeclLoc, T2, 0) &&
RefRelationship == Sema::Ref_Incompatible) {
if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc,
Init, T2, false,
AllowExplicit))
return ICS;
}
}
if (!isRValRef && (!T1.isConstQualified() || T1.isVolatileQualified()))
return ICS;
if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification &&
(InitCategory.isXValue() ||
(InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) ||
(InitCategory.isLValue() && T2->isFunctionType()))) {
ICS.setStandard();
ICS.Standard.First = ICK_Identity;
ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base
: ObjCConversion? ICK_Compatible_Conversion
: ICK_Identity;
ICS.Standard.Third = ICK_Identity;
ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
ICS.Standard.setToType(0, T2);
ICS.Standard.setToType(1, T1);
ICS.Standard.setToType(2, T1);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding =
S.getLangOpts().CPlusPlus11 ||
(InitCategory.isPRValue() && !T2->isRecordType());
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
ICS.Standard.BindsToRvalue = InitCategory.isRValue();
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
ICS.Standard.CopyConstructor = 0;
ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
return ICS;
}
if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) &&
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 (RefRelationship == Sema::Ref_Related) {
Qualifiers T1Quals = T1.getQualifiers();
Qualifiers T2Quals = T2.getQualifiers();
T1Quals.removeObjCGCAttr();
T1Quals.removeObjCLifetime();
T2Quals.removeObjCGCAttr();
T2Quals.removeObjCLifetime();
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())
return ICS;
ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions,
false,
false,
false,
false,
false);
if (ICS.isStandard()) {
ICS.Standard.ReferenceBinding = true;
ICS.Standard.IsLvalueReference = !isRValRef;
ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType();
ICS.Standard.BindsToRvalue = true;
ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
ICS.Standard.ObjCLifetimeConversionBinding = false;
} else if (ICS.isUserDefined()) {
if (DeclType->isRValueReferenceType()) {
if (const ReferenceType *RefType =
ICS.UserDefined.ConversionFunction->getReturnType()
->getAs<LValueReferenceType>()) {
if (!RefType->getPointeeType()->isFunctionType()) {
ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, Init,
DeclType);
return ICS;
}
}
}
ICS.UserDefined.After.ReferenceBinding = true;
ICS.UserDefined.After.IsLvalueReference = !isRValRef;
ICS.UserDefined.After.BindsToFunctionLvalue = T2->isFunctionType();
ICS.UserDefined.After.BindsToRvalue = true;
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);
if (S.RequireCompleteType(From->getLocStart(), ToType, 0))
return Result;
bool toStdInitializerList = false;
QualType X;
if (ToType->isArrayType())
X = S.Context.getAsArrayType(ToType)->getElementType();
else
toStdInitializerList = S.isStdInitializerList(ToType, &X);
if (!X.isNull()) {
for (unsigned i = 0, e = From->getNumInits(); i < e; ++i) {
Expr *Init = From->getInit(i);
ImplicitConversionSequence ICS =
TryCopyInitialization(S, Init, X, SuppressUserConversions,
InOverloadResolution,
AllowObjCWritebackConversion);
if (ICS.isBad()) {
Result = ICS;
break;
}
if (Result.isBad() ||
CompareImplicitConversionSequences(S, ICS, Result) ==
ImplicitConversionSequence::Worse)
Result = ICS;
}
if (From->getNumInits() == 0) {
Result.setStandard();
Result.Standard.setAsIdentityConversion();
Result.Standard.setFromType(ToType);
Result.Standard.setAllToTypes(ToType);
}
Result.setStdInitializerListElement(toStdInitializerList);
return Result;
}
if (ToType->isRecordType() && !ToType->isAggregateType()) {
return TryUserDefinedConversion(S, From, ToType, SuppressUserConversions,
false,
InOverloadResolution, false,
AllowObjCWritebackConversion,
false);
}
if (ToType->isAggregateType()) {
InitializedEntity Entity =
InitializedEntity::InitializeParameter(S.Context, ToType,
false);
if (S.CanPerformCopyInitialization(Entity, S.Owned(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 = 0;
}
return Result;
}
if (ToType->isReferenceType()) {
QualType T1 = ToType->getAs<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();
}
bool dummy1 = false;
bool dummy2 = false;
bool dummy3 = false;
Sema::ReferenceCompareResult RefRelationship
= S.CompareReferenceRelationship(From->getLocStart(), T1, T2, dummy1,
dummy2, dummy3);
if (RefRelationship >= Sema::Ref_Related) {
return TryReferenceInit(S, Init, ToType, From->getLocStart(),
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)
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->getLocStart(),
SuppressUserConversions,
AllowExplicit);
return TryImplicitConversion(S, From, ToType,
SuppressUserConversions,
false,
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, QualType FromType,
Expr::Classification FromClassification,
CXXMethodDecl *Method,
CXXRecordDecl *ActingContext) {
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
unsigned Quals = isa<CXXDestructorDecl>(Method) ?
Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers();
QualType ImplicitParamType = S.Context.getCVRQualifiedType(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;
}
QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType);
ImplicitConversionKind SecondKind;
if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) {
SecondKind = ICK_Identity;
} else if (S.IsDerivedFrom(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 != Qualifiers::Const) {
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(Context)->getAs<PointerType>()->getPointeeType();
Expr::Classification FromClassification;
if (const PointerType *PT = From->getType()->getAs<PointerType>()) {
FromRecordType = PT->getPointeeType();
DestType = Method->getThisType(Context);
FromClassification = Expr::Classification::makeSimpleLValue();
} else {
FromRecordType = From->getType();
DestType = ImplicitParamRecordType;
FromClassification = From->Classify(Context);
}
ImplicitConversionSequence ICS
= TryObjectArgumentInitialization(*this, From->getType(), FromClassification,
Method, Method->getParent());
if (ICS.isBad()) {
if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) {
Qualifiers FromQs = FromRecordType.getQualifiers();
Qualifiers ToQs = DestType.getQualifiers();
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
if (CVR) {
Diag(From->getLocStart(),
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();
}
}
return Diag(From->getLocStart(),
diag::err_implicit_object_parameter_init)
<< 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.take();
}
if (!Context.hasSameType(From->getType(), DestType))
From = ImpCastExprToType(From, DestType, CK_NoOp,
From->getValueKind()).take();
return Owned(From);
}
static ImplicitConversionSequence
TryContextuallyConvertToBool(Sema &S, Expr *From) {
return TryImplicitConversion(S, From, S.Context.BoolTy,
false,
true,
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->getLocStart(),
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_Event_Conversion:
return true;
case ICK_Boolean_Conversion:
return SCS.getFromType()->isIntegralOrUnscopedEnumerationType() &&
SCS.getToType(2)->isBooleanType();
case ICK_Floating_Integral:
case ICK_Complex_Real:
return false;
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
case ICK_NoReturn_Adjustment:
case ICK_Qualification:
case ICK_Compatible_Conversion:
case ICK_Vector_Conversion:
case ICK_Vector_Splat:
case ICK_Derived_To_Base:
case ICK_Pointer_Conversion:
case ICK_Pointer_Member:
case ICK_Block_Pointer_Conversion:
case ICK_Writeback_Conversion:
case ICK_Floating_Promotion:
case ICK_Complex_Promotion:
case ICK_Complex_Conversion:
case ICK_Floating_Conversion:
case ICK_TransparentUnionConversion:
llvm_unreachable("unexpected second conversion kind");
case ICK_Num_Conversion_Kinds:
break;
}
llvm_unreachable("unknown conversion kind");
}
ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
llvm::APSInt &Value,
CCEKind CCE) {
assert(LangOpts.CPlusPlus11 && "converted constant expression outside C++11");
assert(T->isIntegralOrEnumerationType() && "unexpected converted const type");
if (checkPlaceholderForOverload(*this, From))
return ExprError();
ImplicitConversionSequence ICS =
TryImplicitConversion(From, T,
false,
false,
false,
false,
false);
StandardConversionSequence *SCS = 0;
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
if (!CheckConvertedConstantConversions(*this, ICS.Standard))
return Diag(From->getLocStart(),
diag::err_typecheck_converted_constant_expression_disallowed)
<< From->getType() << From->getSourceRange() << T;
SCS = &ICS.Standard;
break;
case ImplicitConversionSequence::UserDefinedConversion:
if (!CheckConvertedConstantConversions(*this, ICS.UserDefined.After))
return Diag(From->getLocStart(),
diag::err_typecheck_converted_constant_expression_disallowed)
<< From->getType() << From->getSourceRange() << T;
SCS = &ICS.UserDefined.After;
break;
case ImplicitConversionSequence::AmbiguousConversion:
case ImplicitConversionSequence::BadConversion:
if (!DiagnoseMultipleUserDefinedConversion(From, T))
return Diag(From->getLocStart(),
diag::err_typecheck_converted_constant_expression)
<< From->getType() << From->getSourceRange() << T;
return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
llvm_unreachable("ellipsis conversion in converted constant expression");
}
ExprResult Result = PerformImplicitConversion(From, T, ICS, AA_Converting);
if (Result.isInvalid())
return Result;
APValue PreNarrowingValue;
QualType PreNarrowingType;
switch (SCS->getNarrowingKind(Context, Result.get(), PreNarrowingValue,
PreNarrowingType)) {
case NK_Variable_Narrowing:
case NK_Not_Narrowing:
break;
case NK_Constant_Narrowing:
Diag(From->getLocStart(), diag::ext_cce_narrowing)
<< CCE << 1
<< PreNarrowingValue.getAsString(Context, PreNarrowingType) << T;
break;
case NK_Type_Narrowing:
Diag(From->getLocStart(), diag::ext_cce_narrowing)
<< CCE << 0 << From->getType() << T;
break;
}
SmallVector<PartialDiagnosticAt, 8> Notes;
Expr::EvalResult Eval;
Eval.Diag = &Notes;
if (!Result.get()->EvaluateAsRValue(Eval, Context) || !Eval.Val.isInt()) {
Result = ExprError();
} else {
Value = Eval.Val.getInt();
if (Notes.empty()) {
return Result;
}
}
if (Notes.size() == 1 &&
Notes[0].second.getDiagID() == diag::note_invalid_subexpr_in_const_expr)
Diag(Notes[0].first, diag::err_expr_not_cce) << CCE;
else {
Diag(From->getLocStart(), diag::err_expr_not_cce)
<< CCE << From->getSourceRange();
for (unsigned I = 0; I < Notes.size(); ++I)
Diag(Notes[I].first, Notes[I].second);
}
return Result;
}
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,
true,
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 ExprError();
}
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 SemaRef.Owned(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->getLocStart(),
"static_cast<" + TypeStr + ">(")
<< FixItHint::CreateInsertion(
SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")");
Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
if (SemaRef.isSFINAEContext())
return true;
SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, 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(), 0,
Result.get()->getValueKind());
}
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, 0, 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(), 0,
Result.get()->getValueKind());
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);
else
SemaRef.AddConversionCandidate(Conv, FoundDecl, ActingContext, From,
ToType, CandidateSet,
false);
}
}
ExprResult Sema::PerformContextualImplicitConversion(
SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) {
if (From->isTypeDependent())
return Owned(From);
if (From->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(From);
if (result.isInvalid())
return result;
From = result.take();
}
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 Owned(From);
}
struct TypeDiagnoserPartialDiag : TypeDiagnoser {
ContextualImplicitConverter &Converter;
Expr *From;
TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
: TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
}
} IncompleteDiagnoser(Converter, From);
if (RequireCompleteType(Loc, T, IncompleteDiagnoser))
return Owned(From);
UnresolvedSet<4>
ViableConversions; UnresolvedSet<4> ExplicitConversions;
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator> Conversions =
cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
bool HadMultipleCandidates =
(std::distance(Conversions.first, Conversions.second) > 1);
QualType ToType;
bool HasUniqueTargetType = true;
for (CXXRecordDecl::conversion_iterator I = Conversions.first,
E = Conversions.second;
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
CXXConversionDecl *Conversion;
FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
if (ConvTemplate) {
if (getLangOpts().CPlusPlus1y)
Conversion = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
else
continue; } else
Conversion = cast<CXXConversionDecl>(D);
assert((!ConvTemplate || getLangOpts().CPlusPlus1y) &&
"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().CPlusPlus1y) {
if (ToType.isNull())
ToType = CurToType.getUnqualifiedType();
else if (HasUniqueTargetType &&
(CurToType.getUnqualifiedType() != ToType))
HasUniqueTargetType = false;
}
ViableConversions.addDecl(I.getDecl(), I.getAccess());
}
}
}
if (getLangOpts().CPlusPlus1y) {
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);
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();
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);
}
void
Sema::AddOverloadCandidate(FunctionDecl *Function,
DeclAccessPair FoundDecl,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions,
bool PartialOverloading,
bool AllowExplicit) {
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);
return;
}
}
if (!CandidateSet.isNewCandidate(Function))
return;
CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function);
if (Constructor && Constructor->isDefaulted() && Constructor->isDeleted() &&
Constructor->isMoveConstructor())
return;
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
if (Constructor) {
QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
if (Args.size() == 1 &&
Constructor->isSpecializationCopyingObject() &&
(Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
IsDerivedFrom(Args[0]->getType(), ClassType)))
return;
}
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Function;
Candidate.Viable = true;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
unsigned NumParams = Proto->getNumParams();
if ((Args.size() + (PartialOverloading && Args.size())) > NumParams &&
!Proto->isVariadic()) {
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 = dyn_cast<FunctionDecl>(CurContext))
if (CheckCUDATarget(Caller, Function)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_target;
return;
}
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
if (ArgIdx < NumParams) {
QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
true,
getLangOpts().ObjCAutoRefCount,
AllowExplicit);
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
} else {
Candidate.Conversions[ArgIdx].setEllipsis();
}
}
if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
}
static bool IsNotEnableIfAttr(Attr *A) { return !isa<EnableIfAttr>(A); }
EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,
bool MissingImplicitThis) {
if (!Function->hasAttrs())
return 0;
AttrVec Attrs = Function->getAttrs();
AttrVec::iterator E = std::remove_if(Attrs.begin(), Attrs.end(),
IsNotEnableIfAttr);
if (Attrs.begin() == E)
return 0;
std::reverse(Attrs.begin(), E);
SFINAETrap Trap(*this);
SmallVector<Expr *, 16> ConvertedArgs;
bool InitializationFailed = false;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
if (i == 0 && !MissingImplicitThis && isa<CXXMethodDecl>(Function) &&
!cast<CXXMethodDecl>(Function)->isStatic()) {
CXXMethodDecl *Method = cast<CXXMethodDecl>(Function);
ExprResult R =
PerformObjectArgumentInitialization(Args[0], 0,
Method, Method);
if (R.isInvalid()) {
InitializationFailed = true;
break;
}
ConvertedArgs.push_back(R.take());
} else {
ExprResult R =
PerformCopyInitialization(InitializedEntity::InitializeParameter(
Context,
Function->getParamDecl(i)),
SourceLocation(),
Args[i]);
if (R.isInvalid()) {
InitializationFailed = true;
break;
}
ConvertedArgs.push_back(R.take());
}
}
if (InitializationFailed || Trap.hasErrorOccurred())
return cast<EnableIfAttr>(Attrs[0]);
for (AttrVec::iterator I = Attrs.begin(); I != E; ++I) {
APValue Result;
EnableIfAttr *EIA = cast<EnableIfAttr>(*I);
if (!EIA->getCond()->EvaluateWithSubstitution(
Result, Context, Function,
llvm::ArrayRef<const Expr*>(ConvertedArgs.data(),
ConvertedArgs.size())) ||
!Result.isInt() || !Result.getInt().getBoolValue()) {
return EIA;
}
}
return 0;
}
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
TemplateArgumentListInfo *ExplicitTemplateArgs) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(),
Args[0]->getType(), Args[0]->Classify(Context),
Args.slice(1), CandidateSet,
SuppressUserConversions);
else
AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
SuppressUserConversions);
} else {
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
!cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
AddMethodTemplateCandidate(FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
ExplicitTemplateArgs,
Args[0]->getType(),
Args[0]->Classify(Context), Args.slice(1),
CandidateSet, SuppressUserConversions);
else
AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
ExplicitTemplateArgs, Args,
CandidateSet, SuppressUserConversions);
}
}
}
void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
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,
0,
ObjectType, ObjectClassification,
Args, CandidateSet,
SuppressUserConversions);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
ObjectType, ObjectClassification,
Args,
CandidateSet, SuppressUserConversions);
}
}
void
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
bool SuppressUserConversions) {
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))
return;
if (Method->isDefaulted() && Method->isDeleted() &&
Method->isMoveAssignmentOperator())
return;
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Method;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
unsigned NumParams = Proto->getNumParams();
if (Args.size() > NumParams && !Proto->isVariadic()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_many_arguments;
return;
}
unsigned MinRequiredArgs = Method->getMinRequiredArguments();
if (Args.size() < MinRequiredArgs) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_too_few_arguments;
return;
}
Candidate.Viable = true;
if (Method->isStatic() || ObjectType.isNull())
Candidate.IgnoreObjectArgument = true;
else {
Candidate.Conversions[0]
= TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification,
Method, ActingContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
}
for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) {
if (ArgIdx < NumParams) {
QualType ParamType = Proto->getParamType(ArgIdx);
Candidate.Conversions[ArgIdx + 1]
= TryCopyInitialization(*this, Args[ArgIdx], ParamType,
SuppressUserConversions,
true,
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(Method, Args, true)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
}
void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
Expr::Classification ObjectClassification,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
if (!CandidateSet.isNewCandidate(MethodTmpl))
return;
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args,
Specialization, Info)) {
OverloadCandidate &Candidate = CandidateSet.addCandidate();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = MethodTmpl->getTemplatedDecl();
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
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);
}
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
TemplateDeductionInfo Info(CandidateSet.getLocation());
FunctionDecl *Specialization = 0;
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args,
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 = Args.size();
Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
Info);
return;
}
assert(Specialization && "Missing function template specialization?");
AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
SuppressUserConversions);
}
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) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
if (!CandidateSet.isNewCandidate(Conversion))
return;
if (getLangOpts().CPlusPlus1y && ConvType->isUndeducedType()) {
if (DeduceReturnType(Conversion, From->getExprLoc()))
return;
ConvType = Conversion->getConversionType().getNonReferenceType();
}
if (Conversion->isExplicit() &&
!isAllowableExplicitConversion(*this, ConvType, ToType,
AllowObjCConversionOnExplicit))
return;
EnterExpressionEvaluationContext Unevaluated(*this, Sema::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;
QualType ImplicitParamType = From->getType();
if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
ImplicitParamType = FromPtrType->getPointeeType();
CXXRecordDecl *ConversionContext
= cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
Candidate.Conversions[0]
= TryObjectArgumentInitialization(*this, From->getType(),
From->Classify(Context),
Conversion, ConversionContext);
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
QualType FromCanon
= Context.getCanonicalType(From->getType().getUnqualifiedType());
QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_trivial_conversion;
return;
}
DeclRefExpr ConversionRef(Conversion, false, Conversion->getType(),
VK_LValue, From->getLocStart());
ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack,
Context.getPointerType(Conversion->getType()),
CK_FunctionToPointerDecay,
&ConversionRef, VK_RValue);
QualType ConversionType = Conversion->getConversionType();
if (RequireCompleteType(From->getLocStart(), ConversionType, 0)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_final_conversion;
return;
}
ExprValueKind VK = Expr::getValueKindForType(ConversionType);
QualType CallResultType = ConversionType.getNonLValueExprType(Context);
CallExpr Call(Context, &ConversionFn, None, CallResultType, VK,
From->getLocStart());
ImplicitConversionSequence ICS =
TryCopyInitialization(*this, &Call, 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, ArrayRef<Expr*>())) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
}
void
Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingDC,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet,
bool AllowObjCConversionOnExplicit) {
assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) &&
"Only conversion function templates permitted here");
if (!CandidateSet.isNewCandidate(FunctionTemplate))
return;
TemplateDeductionInfo Info(CandidateSet.getLocation());
CXXConversionDecl *Specialization = 0;
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);
}
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::Unevaluated);
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size() + 1);
Candidate.FoundDecl = FoundDecl;
Candidate.Function = 0;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
Candidate.IgnoreObjectArgument = false;
Candidate.ExplicitCallArguments = Args.size();
ImplicitConversionSequence ObjectInit
= TryObjectArgumentInitialization(*this, 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, ArrayRef<Expr*>())) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
}
void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
SourceRange OpRange) {
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
QualType T1 = Args[0]->getType();
if (const RecordType *T1Rec = T1->getAs<RecordType>()) {
RequireCompleteType(OpLoc, T1, 0);
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);
}
}
void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
ArrayRef<Expr *> Args,
OverloadCandidateSet& CandidateSet,
bool IsAssignmentOperator,
unsigned NumContextualBoolArguments) {
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
Candidate.Function = 0;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.BuiltinTypes.ResultTy = ResultTy;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx)
Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx];
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::SmallPtrSet<QualType, 8> TypeSet;
TypeSet PointerTypes;
TypeSet MemberPointerTypes;
TypeSet EnumerationTypes;
TypeSet VectorTypes;
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);
iterator pointer_begin() { return PointerTypes.begin(); }
iterator pointer_end() { return PointerTypes.end(); }
iterator member_pointer_begin() { return MemberPointerTypes.begin(); }
iterator member_pointer_end() { return MemberPointerTypes.end(); }
iterator enumeration_begin() { return EnumerationTypes.begin(); }
iterator enumeration_end() { return EnumerationTypes.end(); }
iterator vector_begin() { return VectorTypes.begin(); }
iterator vector_end() { return VectorTypes.end(); }
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->isNullPtrType()) {
HasNullPtrType = true;
} else if (AllowUserConversions && TyRec) {
if (SemaRef.RequireCompleteType(Loc, Ty, 0))
return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator>
Conversions = ClassDecl->getVisibleConversionFunctions();
for (CXXRecordDecl::conversion_iterator
I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = I.getDecl();
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 void AddBuiltinAssignmentOperatorCandidates(Sema &S,
QualType T,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet) {
QualType ParamTypes[2];
ParamTypes[0] = S.Context.getLValueReferenceType(T);
ParamTypes[1] = T;
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
true);
if (!S.Context.getCanonicalType(T).isVolatileQualified()) {
ParamTypes[0]
= S.Context.getLValueReferenceType(S.Context.getVolatileType(T));
ParamTypes[1] = T;
S.AddBuiltinCandidate(ParamTypes[0], 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;
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator>
Conversions = ClassDecl->getVisibleConversionFunctions();
for (CXXRecordDecl::conversion_iterator
I = Conversions.first, E = Conversions.second; I != E; ++I) {
NamedDecl *D = I.getDecl();
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;
}
namespace {
class BuiltinOperatorOverloadBuilder {
Sema &S;
ArrayRef<Expr *> Args;
Qualifiers VisibleTypeConversionsQuals;
bool HasArithmeticOrEnumeralCandidateType;
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
OverloadCandidateSet &CandidateSet;
static const unsigned FirstIntegralType = 3;
static const unsigned LastIntegralType = 20;
static const unsigned FirstPromotedIntegralType = 3,
LastPromotedIntegralType = 11;
static const unsigned FirstPromotedArithmeticType = 0,
LastPromotedArithmeticType = 11;
static const unsigned NumArithmeticTypes = 20;
CanQualType getArithmeticType(unsigned index) {
assert(index < NumArithmeticTypes);
static CanQualType ASTContext::* const
ArithmeticTypes[NumArithmeticTypes] = {
&ASTContext::FloatTy,
&ASTContext::DoubleTy,
&ASTContext::LongDoubleTy,
&ASTContext::IntTy,
&ASTContext::LongTy,
&ASTContext::LongLongTy,
&ASTContext::Int128Ty,
&ASTContext::UnsignedIntTy,
&ASTContext::UnsignedLongTy,
&ASTContext::UnsignedLongLongTy,
&ASTContext::UnsignedInt128Ty,
&ASTContext::BoolTy,
&ASTContext::CharTy,
&ASTContext::WCharTy,
&ASTContext::Char16Ty,
&ASTContext::Char32Ty,
&ASTContext::SignedCharTy,
&ASTContext::ShortTy,
&ASTContext::UnsignedCharTy,
&ASTContext::UnsignedShortTy,
};
return S.Context.*ArithmeticTypes[index];
}
CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) {
enum PromotedType {
Dep=-1,
Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128
};
static const PromotedType ConversionsTable[LastPromotedArithmeticType]
[LastPromotedArithmeticType] = {
{ Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt, Flt, Flt },
{ Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl },
{ LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl },
{ Flt, Dbl, LDbl, SI, SL, SLL, S128, UI, UL, ULL, U128 },
{ Flt, Dbl, LDbl, SL, SL, SLL, S128, Dep, UL, ULL, U128 },
{ Flt, Dbl, LDbl, SLL, SLL, SLL, S128, Dep, Dep, ULL, U128 },
{ Flt, Dbl, LDbl, S128, S128, S128, S128, S128, S128, S128, U128 },
{ Flt, Dbl, LDbl, UI, Dep, Dep, S128, UI, UL, ULL, U128 },
{ Flt, Dbl, LDbl, UL, UL, Dep, S128, UL, UL, ULL, U128 },
{ Flt, Dbl, LDbl, ULL, ULL, ULL, S128, ULL, ULL, ULL, U128 },
{ Flt, Dbl, LDbl, U128, U128, U128, U128, U128, U128, U128, U128 },
};
assert(L < LastPromotedArithmeticType);
assert(R < LastPromotedArithmeticType);
int Idx = ConversionsTable[L][R];
if (Idx != Dep) return getArithmeticType(Idx);
CanQualType LT = getArithmeticType(L),
RT = getArithmeticType(R);
unsigned LW = S.Context.getIntWidth(LT),
RW = S.Context.getIntWidth(RT);
if (LW > RW) return LT;
else if (LW < RW) return RT;
if (L == SL || R == SL) return S.Context.UnsignedLongTy;
assert(L == SLL || R == SLL);
return S.Context.UnsignedLongLongTy;
}
void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy,
bool HasVolatile,
bool HasRestrict) {
QualType ParamTypes[2] = {
S.Context.getLValueReferenceType(CandidateTy),
S.Context.IntTy
};
if (Args.size() == 1)
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
else
S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
if (HasVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(
S.Context.getVolatileType(CandidateTy));
if (Args.size() == 1)
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
else
S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
}
if (HasRestrict && CandidateTy->isAnyPointerType() &&
!CandidateTy.isRestrictQualified()) {
ParamTypes[0]
= S.Context.getLValueReferenceType(
S.Context.getCVRQualifiedType(CandidateTy, Qualifiers::Restrict));
if (Args.size() == 1)
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
else
S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
if (HasVolatile) {
ParamTypes[0]
= S.Context.getLValueReferenceType(
S.Context.getCVRQualifiedType(CandidateTy,
(Qualifiers::Volatile |
Qualifiers::Restrict)));
if (Args.size() == 1)
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
else
S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, CandidateSet);
}
}
}
public:
BuiltinOperatorOverloadBuilder(
Sema &S, ArrayRef<Expr *> Args,
Qualifiers VisibleTypeConversionsQuals,
bool HasArithmeticOrEnumeralCandidateType,
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes,
OverloadCandidateSet &CandidateSet)
: S(S), Args(Args),
VisibleTypeConversionsQuals(VisibleTypeConversionsQuals),
HasArithmeticOrEnumeralCandidateType(
HasArithmeticOrEnumeralCandidateType),
CandidateTypes(CandidateTypes),
CandidateSet(CandidateSet) {
assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy &&
"Invalid first promoted integral type");
assert(getArithmeticType(LastPromotedIntegralType - 1)
== S.Context.UnsignedInt128Ty &&
"Invalid last promoted integral type");
assert(getArithmeticType(FirstPromotedArithmeticType)
== S.Context.FloatTy &&
"Invalid first promoted arithmetic type");
assert(getArithmeticType(LastPromotedArithmeticType - 1)
== S.Context.UnsignedInt128Ty &&
"Invalid last promoted arithmetic type");
}
void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1);
Arith < NumArithmeticTypes; ++Arith) {
addPlusPlusMinusMinusStyleOverloads(
getArithmeticType(Arith),
VisibleTypeConversionsQuals.hasVolatile(),
VisibleTypeConversionsQuals.hasRestrict());
}
}
void addPlusPlusMinusMinusPointerOverloads() {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[0].pointer_begin(),
PtrEnd = CandidateTypes[0].pointer_end();
Ptr != PtrEnd; ++Ptr) {
if (!(*Ptr)->getPointeeType()->isObjectType())
continue;
addPlusPlusMinusMinusStyleOverloads(*Ptr,
(!(*Ptr).isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile()),
(!(*Ptr).isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()));
}
}
void addUnaryStarPointerOverloads() {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[0].pointer_begin(),
PtrEnd = CandidateTypes[0].pointer_end();
Ptr != PtrEnd; ++Ptr) {
QualType ParamTy = *Ptr;
QualType PointeeTy = ParamTy->getPointeeType();
if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType())
continue;
if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>())
if (Proto->getTypeQuals() || Proto->getRefQualifier())
continue;
S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy),
&ParamTy, Args, CandidateSet);
}
}
void addUnaryPlusOrMinusArithmeticOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Arith = FirstPromotedArithmeticType;
Arith < LastPromotedArithmeticType; ++Arith) {
QualType ArithTy = getArithmeticType(Arith);
S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, CandidateSet);
}
for (BuiltinCandidateTypeSet::iterator
Vec = CandidateTypes[0].vector_begin(),
VecEnd = CandidateTypes[0].vector_end();
Vec != VecEnd; ++Vec) {
QualType VecTy = *Vec;
S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet);
}
}
void addUnaryPlusPointerOverloads() {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[0].pointer_begin(),
PtrEnd = CandidateTypes[0].pointer_end();
Ptr != PtrEnd; ++Ptr) {
QualType ParamTy = *Ptr;
S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet);
}
}
void addUnaryTildePromotedIntegralOverloads() {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Int = FirstPromotedIntegralType;
Int < LastPromotedIntegralType; ++Int) {
QualType IntTy = getArithmeticType(Int);
S.AddBuiltinCandidate(IntTy, &IntTy, Args, CandidateSet);
}
for (BuiltinCandidateTypeSet::iterator
Vec = CandidateTypes[0].vector_begin(),
VecEnd = CandidateTypes[0].vector_end();
Vec != VecEnd; ++Vec) {
QualType VecTy = *Vec;
S.AddBuiltinCandidate(VecTy, &VecTy, Args, CandidateSet);
}
}
void addEqualEqualOrNotEqualMemberPointerOverloads() {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
for (BuiltinCandidateTypeSet::iterator
MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
MemPtr != MemPtrEnd;
++MemPtr) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
continue;
QualType ParamTypes[2] = { *MemPtr, *MemPtr };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
}
}
}
void addRelationalPointerOrEnumeralOverloads() {
llvm::DenseSet<std::pair<CanQualType, CanQualType> >
UserDefinedBinaryOperators;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
if (CandidateTypes[ArgIdx].enumeration_begin() !=
CandidateTypes[ArgIdx].enumeration_end()) {
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;
QualType FirstParamType =
C->Function->getParamDecl(0)->getType().getUnqualifiedType();
QualType SecondParamType =
C->Function->getParamDecl(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 (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[ArgIdx].pointer_begin(),
PtrEnd = CandidateTypes[ArgIdx].pointer_end();
Ptr != PtrEnd; ++Ptr) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
continue;
QualType ParamTypes[2] = { *Ptr, *Ptr };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
}
for (BuiltinCandidateTypeSet::iterator
Enum = CandidateTypes[ArgIdx].enumeration_begin(),
EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
Enum != EnumEnd; ++Enum) {
CanQualType CanonType = S.Context.getCanonicalType(*Enum);
if (!AddedTypes.insert(CanonType) ||
UserDefinedBinaryOperators.count(std::make_pair(CanonType,
CanonType)))
continue;
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet);
}
if (CandidateTypes[ArgIdx].hasNullPtrType()) {
CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy);
if (AddedTypes.insert(NullPtrTy) &&
!UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy,
NullPtrTy))) {
QualType ParamTypes[2] = { NullPtrTy, NullPtrTy };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args,
CandidateSet);
}
}
}
}
void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (int Arg = 0; Arg < 2; ++Arg) {
QualType AsymetricParamTypes[2] = {
S.Context.getPointerDiffType(),
S.Context.getPointerDiffType(),
};
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[Arg].pointer_begin(),
PtrEnd = CandidateTypes[Arg].pointer_end();
Ptr != PtrEnd; ++Ptr) {
QualType PointeeTy = (*Ptr)->getPointeeType();
if (!PointeeTy->isObjectType())
continue;
AsymetricParamTypes[Arg] = *Ptr;
if (Arg == 0 || Op == OO_Plus) {
S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, CandidateSet);
}
if (Op == OO_Minus) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
continue;
QualType ParamTypes[2] = { *Ptr, *Ptr };
S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes,
Args, CandidateSet);
}
}
}
}
void addGenericBinaryArithmeticOverloads(bool isComparison) {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Left = FirstPromotedArithmeticType;
Left < LastPromotedArithmeticType; ++Left) {
for (unsigned Right = FirstPromotedArithmeticType;
Right < LastPromotedArithmeticType; ++Right) {
QualType LandR[2] = { getArithmeticType(Left),
getArithmeticType(Right) };
QualType Result =
isComparison ? S.Context.BoolTy
: getUsualArithmeticConversions(Left, Right);
S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet);
}
}
for (BuiltinCandidateTypeSet::iterator
Vec1 = CandidateTypes[0].vector_begin(),
Vec1End = CandidateTypes[0].vector_end();
Vec1 != Vec1End; ++Vec1) {
for (BuiltinCandidateTypeSet::iterator
Vec2 = CandidateTypes[1].vector_begin(),
Vec2End = CandidateTypes[1].vector_end();
Vec2 != Vec2End; ++Vec2) {
QualType LandR[2] = { *Vec1, *Vec2 };
QualType Result = S.Context.BoolTy;
if (!isComparison) {
if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType())
Result = *Vec1;
else
Result = *Vec2;
}
S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet);
}
}
}
void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) {
if (!HasArithmeticOrEnumeralCandidateType)
return;
for (unsigned Left = FirstPromotedIntegralType;
Left < LastPromotedIntegralType; ++Left) {
for (unsigned Right = FirstPromotedIntegralType;
Right < LastPromotedIntegralType; ++Right) {
QualType LandR[2] = { getArithmeticType(Left),
getArithmeticType(Right) };
QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater)
? LandR[0]
: getUsualArithmeticConversions(Left, Right);
S.AddBuiltinCandidate(Result, LandR, Args, CandidateSet);
}
}
}
void addAssignmentMemberPointerOrEnumeralOverloads() {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
for (BuiltinCandidateTypeSet::iterator
Enum = CandidateTypes[ArgIdx].enumeration_begin(),
EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
Enum != EnumEnd; ++Enum) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
continue;
AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, CandidateSet);
}
for (BuiltinCandidateTypeSet::iterator
MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
MemPtr != MemPtrEnd; ++MemPtr) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
continue;
AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, CandidateSet);
}
}
}
void addAssignmentPointerOverloads(bool isEqualOp) {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[0].pointer_begin(),
PtrEnd = CandidateTypes[0].pointer_end();
Ptr != PtrEnd; ++Ptr) {
if (isEqualOp)
AddedTypes.insert(S.Context.getCanonicalType(*Ptr));
else if (!(*Ptr)->getPointeeType()->isObjectType())
continue;
QualType ParamTypes[2] = {
S.Context.getLValueReferenceType(*Ptr),
isEqualOp ? *Ptr : S.Context.getPointerDiffType(),
};
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
bool NeedVolatile = !(*Ptr).isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile();
if (NeedVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
}
if (!(*Ptr).isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()) {
ParamTypes[0]
= S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
if (NeedVolatile) {
ParamTypes[0]
= S.Context.getLValueReferenceType(
S.Context.getCVRQualifiedType(*Ptr,
(Qualifiers::Volatile |
Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
}
}
}
if (isEqualOp) {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[1].pointer_begin(),
PtrEnd = CandidateTypes[1].pointer_end();
Ptr != PtrEnd; ++Ptr) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
continue;
QualType ParamTypes[2] = {
S.Context.getLValueReferenceType(*Ptr),
*Ptr,
};
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
true);
bool NeedVolatile = !(*Ptr).isVolatileQualified() &&
VisibleTypeConversionsQuals.hasVolatile();
if (NeedVolatile) {
ParamTypes[0] =
S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
true);
}
if (!(*Ptr).isRestrictQualified() &&
VisibleTypeConversionsQuals.hasRestrict()) {
ParamTypes[0]
= S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
true);
if (NeedVolatile) {
ParamTypes[0]
= S.Context.getLValueReferenceType(
S.Context.getCVRQualifiedType(*Ptr,
(Qualifiers::Volatile |
Qualifiers::Restrict)));
S.AddBuiltinCandidate(ParamTypes[0], 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] = getArithmeticType(Right);
ParamTypes[0] =
S.Context.getLValueReferenceType(getArithmeticType(Left));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
if (VisibleTypeConversionsQuals.hasVolatile()) {
ParamTypes[0] =
S.Context.getVolatileType(getArithmeticType(Left));
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
}
}
}
for (BuiltinCandidateTypeSet::iterator
Vec1 = CandidateTypes[0].vector_begin(),
Vec1End = CandidateTypes[0].vector_end();
Vec1 != Vec1End; ++Vec1) {
for (BuiltinCandidateTypeSet::iterator
Vec2 = CandidateTypes[1].vector_begin(),
Vec2End = CandidateTypes[1].vector_end();
Vec2 != Vec2End; ++Vec2) {
QualType ParamTypes[2];
ParamTypes[1] = *Vec2;
ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1);
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet,
isEqualOp);
if (VisibleTypeConversionsQuals.hasVolatile()) {
ParamTypes[0] = S.Context.getVolatileType(*Vec1);
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes[0], 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] = getArithmeticType(Right);
ParamTypes[0] =
S.Context.getLValueReferenceType(getArithmeticType(Left));
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
if (VisibleTypeConversionsQuals.hasVolatile()) {
ParamTypes[0] = getArithmeticType(Left);
ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]);
ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]);
S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, CandidateSet);
}
}
}
}
void addExclaimOverload() {
QualType ParamTy = S.Context.BoolTy;
S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, CandidateSet,
false,
1);
}
void addAmpAmpOrPipePipeOverload() {
QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy };
S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, CandidateSet,
false,
2);
}
void addSubscriptOverloads() {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[0].pointer_begin(),
PtrEnd = CandidateTypes[0].pointer_end();
Ptr != PtrEnd; ++Ptr) {
QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() };
QualType PointeeType = (*Ptr)->getPointeeType();
if (!PointeeType->isObjectType())
continue;
QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet);
}
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[1].pointer_begin(),
PtrEnd = CandidateTypes[1].pointer_end();
Ptr != PtrEnd; ++Ptr) {
QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr };
QualType PointeeType = (*Ptr)->getPointeeType();
if (!PointeeType->isObjectType())
continue;
QualType ResultTy = S.Context.getLValueReferenceType(PointeeType);
S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet);
}
}
void addArrowStarOverloads() {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[0].pointer_begin(),
PtrEnd = CandidateTypes[0].pointer_end();
Ptr != PtrEnd; ++Ptr) {
QualType C1Ty = (*Ptr);
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 (BuiltinCandidateTypeSet::iterator
MemPtr = CandidateTypes[1].member_pointer_begin(),
MemPtrEnd = CandidateTypes[1].member_pointer_end();
MemPtr != MemPtrEnd; ++MemPtr) {
const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
QualType C2 = QualType(mptr->getClass(), 0);
C2 = C2.getUnqualifiedType();
if (C1 != C2 && !S.IsDerivedFrom(C1, C2))
break;
QualType ParamTypes[2] = { *Ptr, *MemPtr };
QualType T = mptr->getPointeeType();
if (!VisibleTypeConversionsQuals.hasVolatile() &&
T.isVolatileQualified())
continue;
if (!VisibleTypeConversionsQuals.hasRestrict() &&
T.isRestrictQualified())
continue;
T = Q1.apply(S.Context, T);
QualType ResultTy = S.Context.getLValueReferenceType(T);
S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, CandidateSet);
}
}
}
void addConditionalOperatorOverloads() {
llvm::SmallPtrSet<QualType, 8> AddedTypes;
for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) {
for (BuiltinCandidateTypeSet::iterator
Ptr = CandidateTypes[ArgIdx].pointer_begin(),
PtrEnd = CandidateTypes[ArgIdx].pointer_end();
Ptr != PtrEnd; ++Ptr) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr)))
continue;
QualType ParamTypes[2] = { *Ptr, *Ptr };
S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, CandidateSet);
}
for (BuiltinCandidateTypeSet::iterator
MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
MemPtr != MemPtrEnd; ++MemPtr) {
if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr)))
continue;
QualType ParamTypes[2] = { *MemPtr, *MemPtr };
S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, CandidateSet);
}
if (S.getLangOpts().CPlusPlus11) {
for (BuiltinCandidateTypeSet::iterator
Enum = CandidateTypes[ArgIdx].enumeration_begin(),
EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
Enum != EnumEnd; ++Enum) {
if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
continue;
if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum)))
continue;
QualType ParamTypes[2] = { *Enum, *Enum };
S.AddBuiltinCandidate(*Enum, ParamTypes, Args, CandidateSet);
}
}
}
}
};
}
void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet) {
Qualifiers VisibleTypeConversionsQuals;
VisibleTypeConversionsQuals.addConst();
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx)
VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
bool HasNonRecordCandidateType = false;
bool HasArithmeticOrEnumeralCandidateType = false;
SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
for (unsigned ArgIdx = 0, N = Args.size(); ArgIdx != N; ++ArgIdx) {
CandidateTypes.push_back(BuiltinCandidateTypeSet(*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:
break;
case OO_Plus: if (Args.size() == 1)
OpBuilder.addUnaryPlusPointerOverloads();
case OO_Minus: if (Args.size() == 1) {
OpBuilder.addUnaryPlusOrMinusArithmeticOverloads();
} else {
OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op);
OpBuilder.addGenericBinaryArithmeticOverloads(false);
}
break;
case OO_Star: if (Args.size() == 1)
OpBuilder.addUnaryStarPointerOverloads();
else
OpBuilder.addGenericBinaryArithmeticOverloads(false);
break;
case OO_Slash:
OpBuilder.addGenericBinaryArithmeticOverloads(false);
break;
case OO_PlusPlus:
case OO_MinusMinus:
OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op);
OpBuilder.addPlusPlusMinusMinusPointerOverloads();
break;
case OO_EqualEqual:
case OO_ExclaimEqual:
OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads();
case OO_Less:
case OO_Greater:
case OO_LessEqual:
case OO_GreaterEqual:
OpBuilder.addRelationalPointerOrEnumeralOverloads();
OpBuilder.addGenericBinaryArithmeticOverloads(true);
break;
case OO_Percent:
case OO_Caret:
case OO_Pipe:
case OO_LessLess:
case OO_GreaterGreater:
OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
break;
case OO_Amp: if (Args.size() == 1)
break;
OpBuilder.addBinaryBitwiseArithmeticOverloads(Op);
break;
case OO_Tilde:
OpBuilder.addUnaryTildePromotedIntegralOverloads();
break;
case OO_Equal:
OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads();
case OO_PlusEqual:
case OO_MinusEqual:
OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal);
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:
OpBuilder.addSubscriptOverloads();
break;
case OO_ArrowStar:
OpBuilder.addArrowStarOverloads();
break;
case OO_Conditional:
OpBuilder.addConditionalOperatorOverloads();
OpBuilder.addGenericBinaryArithmeticOverloads(false);
break;
}
}
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
bool Operator, SourceLocation Loc,
ArrayRef<Expr *> Args,
TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
ADLResult Fns;
ArgumentDependentLookup(Name, Operator, 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);
} else
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
FoundDecl, ExplicitTemplateArgs,
Args, CandidateSet);
}
}
bool
isBetterOverloadCandidate(Sema &S,
const OverloadCandidate &Cand1,
const OverloadCandidate &Cand2,
SourceLocation Loc,
bool UserDefinedConversion) {
if (!Cand2.Viable)
return Cand1.Viable;
else if (!Cand1.Viable)
return false;
unsigned StartArg = 0;
if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument)
StartArg = 1;
unsigned NumArgs = Cand1.NumConversions;
assert(Cand2.NumConversions == NumArgs && "Overload candidate mismatch");
bool HasBetterConversion = false;
for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) {
switch (CompareImplicitConversionSequences(S,
Cand1.Conversions[ArgIdx],
Cand2.Conversions[ArgIdx])) {
case ImplicitConversionSequence::Better:
HasBetterConversion = true;
break;
case ImplicitConversionSequence::Worse:
return false;
case ImplicitConversionSequence::Indistinguishable:
break;
}
}
if (HasBetterConversion)
return true;
if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) &&
Cand2.Function && Cand2.Function->getPrimaryTemplate())
return true;
if (Cand1.Function && Cand1.Function->getPrimaryTemplate() &&
Cand2.Function && Cand2.Function->getPrimaryTemplate()) {
if (FunctionTemplateDecl *BetterTemplate
= S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(),
Cand2.Function->getPrimaryTemplate(),
Loc,
isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion
: TPOC_Call,
Cand1.ExplicitCallArguments,
Cand2.ExplicitCallArguments))
return BetterTemplate == Cand1.Function->getPrimaryTemplate();
}
if (UserDefinedConversion && Cand1.Function && Cand2.Function &&
isa<CXXConversionDecl>(Cand1.Function) &&
isa<CXXConversionDecl>(Cand2.Function)) {
ImplicitConversionSequence::CompareKind FuncResult
= compareConversionFunctions(S, Cand1.Function, Cand2.Function);
if (FuncResult != ImplicitConversionSequence::Indistinguishable)
return FuncResult;
switch (CompareStandardConversionSequences(S,
Cand1.FinalConversion,
Cand2.FinalConversion)) {
case ImplicitConversionSequence::Better:
return true;
case ImplicitConversionSequence::Worse:
return false;
case ImplicitConversionSequence::Indistinguishable:
break;
}
}
if (Cand1.Function && Cand2.Function &&
(Cand1.Function->hasAttr<EnableIfAttr>() ||
Cand2.Function->hasAttr<EnableIfAttr>())) {
AttrVec Cand1Attrs;
AttrVec::iterator Cand1E = Cand1Attrs.end();
if (Cand1.Function->hasAttrs()) {
Cand1Attrs = Cand1.Function->getAttrs();
Cand1E = std::remove_if(Cand1Attrs.begin(), Cand1Attrs.end(),
IsNotEnableIfAttr);
std::reverse(Cand1Attrs.begin(), Cand1E);
}
AttrVec Cand2Attrs;
AttrVec::iterator Cand2E = Cand2Attrs.end();
if (Cand2.Function->hasAttrs()) {
Cand2Attrs = Cand2.Function->getAttrs();
Cand2E = std::remove_if(Cand2Attrs.begin(), Cand2Attrs.end(),
IsNotEnableIfAttr);
std::reverse(Cand2Attrs.begin(), Cand2E);
}
for (AttrVec::iterator
Cand1I = Cand1Attrs.begin(), Cand2I = Cand2Attrs.begin();
Cand1I != Cand1E || Cand2I != Cand2E; ++Cand1I, ++Cand2I) {
if (Cand1I == Cand1E)
return false;
if (Cand2I == Cand2E)
return true;
llvm::FoldingSetNodeID Cand1ID, Cand2ID;
cast<EnableIfAttr>(*Cand1I)->getCond()->Profile(Cand1ID,
S.getASTContext(), true);
cast<EnableIfAttr>(*Cand2I)->getCond()->Profile(Cand2ID,
S.getASTContext(), true);
if (Cand1ID != Cand2ID)
return false;
}
}
return false;
}
OverloadingResult
OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc,
iterator &Best,
bool UserDefinedConversion) {
Best = end();
for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable)
if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc,
UserDefinedConversion))
Best = Cand;
}
if (Best == end())
return OR_No_Viable_Function;
for (iterator Cand = begin(); Cand != end(); ++Cand) {
if (Cand->Viable &&
Cand != Best &&
!isBetterOverloadCandidate(S, *Best, *Cand, Loc,
UserDefinedConversion)) {
Best = end();
return OR_Ambiguous;
}
}
if (Best->Function &&
(Best->Function->isDeleted() ||
S.isFunctionConsideredUnavailable(Best->Function)))
return OR_Deleted;
return OR_Success;
}
namespace {
enum OverloadCandidateKind {
oc_function,
oc_method,
oc_constructor,
oc_function_template,
oc_method_template,
oc_constructor_template,
oc_implicit_default_constructor,
oc_implicit_copy_constructor,
oc_implicit_move_constructor,
oc_implicit_copy_assignment,
oc_implicit_move_assignment,
oc_implicit_inherited_constructor
};
OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
FunctionDecl *Fn,
std::string &Description) {
bool isTemplate = false;
if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) {
isTemplate = true;
Description = S.getTemplateArgumentBindingsText(
FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs());
}
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
if (!Ctor->isImplicit())
return isTemplate ? oc_constructor_template : oc_constructor;
if (Ctor->getInheritedConstructor())
return oc_implicit_inherited_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 isTemplate ? oc_method_template : 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 isTemplate ? oc_function_template : oc_function;
}
void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
if (!Ctor) return;
Ctor = Ctor->getInheritedConstructor();
if (!Ctor) return;
S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor);
}
}
void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType) {
std::string FnDesc;
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
<< (unsigned) K << FnDesc;
HandleFunctionTypeMismatch(PD, Fn->getType(), DestType);
Diag(Fn->getLocation(), PD);
MaybeEmitInheritedConstructorNote(*this, Fn);
}
void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr, QualType DestType) {
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(FunTmpl->getTemplatedDecl(), DestType);
} else if (FunctionDecl *Fun
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
NoteOverloadCandidate(Fun, DestType);
}
}
}
void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
Sema &S,
SourceLocation CaretLoc,
const PartialDiagnostic &PDiag) const {
S.Diag(CaretLoc, PDiag)
<< Ambiguous.getFromType() << Ambiguous.getToType();
const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
unsigned CandsShown = 0;
AmbiguousConversionSequence::const_iterator I, E;
for (I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) {
if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
break;
++CandsShown;
S.NoteOverloadCandidate(*I);
}
if (I != E)
S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I);
}
namespace {
void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
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;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, 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) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< ToTy << Name << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
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()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy
<< FromQs.getAddressSpace() << ToQs.getAddressSpace()
<< (unsigned) isObjectArgument << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy
<< FromQs.getObjCLifetime() << ToQs.getObjCLifetime()
<< (unsigned) isObjectArgument << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy
<< FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr()
<< (unsigned) isObjectArgument << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
assert(CVR && "unexpected qualifiers mismatch");
if (isObjectArgument) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << (CVR - 1);
} else {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << (CVR - 1) << I+1;
}
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
if (FromExpr && isa<InitListExpr>(FromExpr)) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
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) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
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(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(ToRefTy->getPointeeType(), FromTy)) {
BaseToDerivedConversion = 3;
} else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() &&
ToTy.getNonReferenceType().getCanonicalType() ==
FromTy.getNonReferenceType().getCanonicalType()) {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< (unsigned) isObjectArgument << I + 1;
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
}
if (BaseToDerivedConversion) {
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_bad_base_to_derived_conv)
<< (unsigned) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< (BaseToDerivedConversion - 1)
<< FromTy << ToTy << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
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) FnKind << FnDesc
<< (FromExpr ? FromExpr->getSourceRange() : SourceRange())
<< FromTy << ToTy << (unsigned) isObjectArgument << I+1;
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
}
PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv);
FDiag << (unsigned) FnKind << 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, Fn);
}
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;
}
void DiagnoseArityMismatch(Sema &S, 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 FunctionProtoType *FnTy = Fn->getType()->getAs<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;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
<< (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
<< Fn->getParamDecl(0) << NumFormalArgs;
else
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
<< (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode
<< modeCount << NumFormalArgs;
MaybeEmitInheritedConstructorNote(S, Fn);
}
void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
unsigned NumFormalArgs) {
if (!CheckArityMismatch(S, Cand, NumFormalArgs))
DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
}
TemplateDecl *getDescribedTemplate(Decl *Templated) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
return FD->getDescribedFunctionTemplate();
else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
return RD->getDescribedClassTemplate();
llvm_unreachable("Unsupported: Getting the described template declaration"
" for bad deduction diagnosis");
}
void DiagnoseBadDeduction(Sema &S, Decl *Templated,
DeductionFailureInfo &DeductionFailure,
unsigned NumArgs) {
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, Templated);
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, Templated);
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))
which = 1;
else {
which = 2;
}
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_inconsistent_deduction)
<< which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
<< *DeductionFailure.getSecondArg();
MaybeEmitInheritedConstructorNote(S, Templated);
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, Templated);
return;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Templated, NumArgs);
return;
case Sema::TDK_InstantiationDepth:
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_instantiation_depth);
MaybeEmitInheritedConstructorNote(S, Templated);
return;
case Sema::TDK_SubstitutionFailure: {
SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
DeductionFailure.getTemplateArgumentList()) {
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
}
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;
}
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, Templated);
return;
}
case Sema::TDK_FailedOverloadResolution: {
OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr());
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_failed_overload_resolution)
<< R.Expression->getName();
return;
}
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;
}
}
}
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, Templated);
return;
}
}
void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
unsigned TDK = Cand->DeductionFailure.Result;
if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
if (CheckArityMismatch(S, Cand, NumArgs))
return;
}
DiagnoseBadDeduction(S, Cand->Function, Cand->DeductionFailure, NumArgs);
}
void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
FunctionDecl *Callee = Cand->Function;
Sema::CUDAFunctionTarget CallerTarget = S.IdentifyCUDATarget(Caller),
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
<< (unsigned) FnKind << CalleeTarget << CallerTarget;
}
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_enable_if_attr)
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
}
void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
if (Cand->Viable && (Fn->isDeleted() ||
S.isFunctionConsideredUnavailable(Fn))) {
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
<< FnKind << FnDesc
<< (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
MaybeEmitInheritedConstructorNote(S, Fn);
return;
}
if (Cand->Viable) {
S.NoteOverloadCandidate(Fn);
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);
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
case ovl_fail_final_conversion_not_exact:
return S.NoteOverloadCandidate(Fn);
case ovl_fail_bad_conversion: {
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
for (unsigned N = Cand->NumConversions; I != N; ++I)
if (Cand->Conversions[I].isBad())
return DiagnoseBadConversion(S, Cand, I);
return S.NoteOverloadCandidate(Fn);
}
case ovl_fail_bad_target:
return DiagnoseBadTarget(S, Cand);
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
}
}
void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
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;
MaybeEmitInheritedConstructorNote(S, Cand->Surrogate);
}
void NoteBuiltinOperatorCandidate(Sema &S,
StringRef Opc,
SourceLocation OpLoc,
OverloadCandidate *Cand) {
assert(Cand->NumConversions <= 2 && "builtin operator is not binary");
std::string TypeStr("operator");
TypeStr += Opc;
TypeStr += "(";
TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
if (Cand->NumConversions == 1) {
TypeStr += ")";
S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
} else {
TypeStr += ", ";
TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
TypeStr += ")";
S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
}
}
void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
OverloadCandidate *Cand) {
unsigned NoOperands = Cand->NumConversions;
for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
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:
llvm_unreachable("TDK_success while diagnosing bad deduction");
case Sema::TDK_Invalid:
case Sema::TDK_Incomplete:
return 1;
case Sema::TDK_Underqualified:
case Sema::TDK_Inconsistent:
return 2;
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
return 3;
case Sema::TDK_InstantiationDepth:
case Sema::TDK_FailedOverloadResolution:
return 4;
case Sema::TDK_InvalidExplicitArguments:
return 5;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
return 6;
}
llvm_unreachable("Unhandled deduction result");
}
struct CompareOverloadCandidatesForDisplay {
Sema &S;
CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {}
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())) return true;
if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false;
} else if (R->Viable)
return false;
assert(L->Viable == R->Viable);
if (!L->Viable) {
if (L->FailureKind == ovl_fail_too_many_arguments ||
L->FailureKind == ovl_fail_too_few_arguments)
return false;
if (R->FailureKind == ovl_fail_too_many_arguments ||
R->FailureKind == ovl_fail_too_few_arguments)
return true;
if (L->FailureKind == ovl_fail_bad_conversion) {
if (R->FailureKind != 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) {
if (numLFixes < numRFixes)
return true;
else
return false;
}
assert(L->NumConversions == R->NumConversions);
int leftBetter = 0;
unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument);
for (unsigned E = L->NumConversions; I != E; ++I) {
switch (CompareImplicitConversionSequences(S,
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 (R->FailureKind == ovl_fail_bad_conversion)
return false;
if (L->FailureKind == ovl_fail_bad_deduction) {
if (R->FailureKind != ovl_fail_bad_deduction)
return true;
if (L->DeductionFailure.Result != R->DeductionFailure.Result)
return RankDeductionFailure(L->DeductionFailure)
< RankDeductionFailure(R->DeductionFailure);
} else if (R->FailureKind == 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);
}
};
void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand,
ArrayRef<Expr *> Args) {
assert(!Cand->Viable);
if (Cand->FailureKind != ovl_fail_bad_conversion) return;
bool Unfixable = false;
Cand->Fix.setConversionChecker(TryCopyInitialization);
unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0);
unsigned ConvCount = Cand->NumConversions;
while (true) {
assert(ConvIdx != ConvCount && "no bad conversion in candidate");
ConvIdx++;
if (Cand->Conversions[ConvIdx - 1].isBad()) {
Unfixable = !Cand->TryToFixBadConversion(ConvIdx - 1, S);
break;
}
}
if (ConvIdx == ConvCount)
return;
assert(!Cand->Conversions[ConvIdx].isInitialized() &&
"remaining conversion is initialized?");
bool SuppressUserConversions = false;
const FunctionProtoType* Proto;
unsigned ArgIdx = ConvIdx;
if (Cand->IsSurrogate) {
QualType ConvType
= Cand->Surrogate->getConversionType().getNonReferenceType();
if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
ConvType = ConvPtrType->getPointeeType();
Proto = ConvType->getAs<FunctionProtoType>();
ArgIdx--;
} else if (Cand->Function) {
Proto = Cand->Function->getType()->getAs<FunctionProtoType>();
if (isa<CXXMethodDecl>(Cand->Function) &&
!isa<CXXConstructorDecl>(Cand->Function))
ArgIdx--;
} else {
assert(ConvCount <= 3);
for (; ConvIdx != ConvCount; ++ConvIdx)
Cand->Conversions[ConvIdx]
= TryCopyInitialization(S, Args[ConvIdx],
Cand->BuiltinTypes.ParamTypes[ConvIdx],
SuppressUserConversions,
true,
S.getLangOpts().ObjCAutoRefCount);
return;
}
unsigned NumParams = Proto->getNumParams();
for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) {
if (ArgIdx < NumParams) {
Cand->Conversions[ConvIdx] = TryCopyInitialization(
S, Args[ArgIdx], Proto->getParamType(ArgIdx), SuppressUserConversions,
true,
S.getLangOpts().ObjCAutoRefCount);
if (!Unfixable && Cand->Conversions[ConvIdx].isBad())
Unfixable = !Cand->TryToFixBadConversion(ConvIdx, S);
}
else
Cand->Conversions[ConvIdx].setEllipsis();
}
}
}
void OverloadCandidateSet::NoteCandidates(Sema &S,
OverloadCandidateDisplayKind OCD,
ArrayRef<Expr *> Args,
StringRef Opc,
SourceLocation OpLoc) {
SmallVector<OverloadCandidate*, 32> Cands;
if (OCD == OCD_AllCandidates) Cands.reserve(size());
for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
if (Cand->Viable)
Cands.push_back(Cand);
else if (OCD == OCD_AllCandidates) {
CompleteNonViableCandidate(S, Cand, Args);
if (Cand->Function || Cand->IsSurrogate)
Cands.push_back(Cand);
}
}
std::sort(Cands.begin(), Cands.end(),
CompareOverloadCandidatesForDisplay(S));
bool ReportedAmbiguousConversions = false;
SmallVectorImpl<OverloadCandidate*>::iterator I, E;
const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
unsigned CandsShown = 0;
for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
OverloadCandidate *Cand = *I;
if (CandsShown >= 4 && ShowOverloads == Ovl_Best) {
break;
}
++CandsShown;
if (Cand->Function)
NoteFunctionCandidate(S, Cand, Args.size());
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);
}
}
if (I != E)
S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
static SourceLocation
GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
return Cand->Specialization ? Cand->Specialization->getLocation()
: SourceLocation();
}
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) {
DiagnoseBadDeduction(S, Specialization, DeductionFailure, 0);
}
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);
}
std::sort(Cands.begin(), Cands.end(),
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);
}
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;
}
class AddressOfFunctionResolver
{
Sema& S;
Expr* SourceExpr;
const QualType& TargetType;
QualType TargetFunctionType;
bool Complain;
ASTContext& Context;
bool TargetTypeIsNonStaticMemberFunction;
bool FoundNonTemplateFunction;
bool StaticMemberFunctionFromBoundPointer;
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),
OvlExprInfo(OverloadExpr::find(SourceExpr)),
OvlExpr(OvlExprInfo.Expression),
FailedCandidates(OvlExpr->getNameLoc()) {
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->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
if (FindAllFunctionsThatMatchTargetTypeExactly()) {
if (Matches.size() > 1) {
if (FoundNonTemplateFunction)
EliminateAllTemplateMatches();
else
EliminateAllExceptMostSpecializedTemplate();
}
}
}
private:
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 = 0;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result
= S.DeduceTemplateArguments(FunctionTemplate,
&OvlExplicitTemplateArgs,
TargetFunctionType, Specialization,
Info, true)) {
FailedCandidates.addCandidate()
.set(FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
return false;
}
Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
assert(S.isSameOrCompatibleFunctionType(
Context.getCanonicalType(Specialization->getType()),
Context.getCanonicalType(TargetFunctionType)));
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 = dyn_cast<FunctionDecl>(S.CurContext))
if (S.CheckCUDATarget(Caller, FunDecl))
return false;
if (S.getLangOpts().CPlusPlus1y &&
FunDecl->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain))
return false;
QualType ResultTy;
if (Context.hasSameUnqualifiedType(TargetFunctionType,
FunDecl->getType()) ||
S.IsNoReturnConversion(FunDecl->getType(), TargetFunctionType,
ResultTy)) {
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->getLocStart(), S.PDiag(),
S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
.second->getDeclName(),
S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template,
Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
Matches[0].second = cast<FunctionDecl>(*Result);
Matches.resize(1);
}
}
void EliminateAllTemplateMatches() {
for (unsigned I = 0, N = Matches.size(); I != N; ) {
if (Matches[I].second->getPrimaryTemplate() == 0)
++I;
else {
Matches[I] = Matches[--N];
Matches.set_size(N);
}
}
}
public:
void ComplainNoMatchesFound() const {
assert(Matches.empty());
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
if (FailedCandidates.empty())
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
else {
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
IEnd = OvlExpr->decls_end();
I != IEnd; ++I)
if (FunctionDecl *Fun =
dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
S.NoteOverloadCandidate(Fun, TargetFunctionType);
FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
}
}
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->getLocStart(),
diag::err_invalid_form_pointer_member_function)
<< OvlExpr->getSourceRange();
}
void ComplainOfInvalidConversion() const {
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
<< OvlExpr->getName() << TargetType;
}
void ComplainMultipleMatchesFound() const {
assert(Matches.size() > 1);
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous)
<< OvlExpr->getName()
<< OvlExpr->getSourceRange();
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
}
bool hadMultipleCandidates() const { return (OvlExpr->getNumDecls() > 1); }
int getNumMatches() const { return Matches.size(); }
FunctionDecl* getMatchingFunctionDecl() const {
if (Matches.size() != 1) return 0;
return Matches[0].second;
}
const DeclAccessPair* getMatchingFunctionAccessPair() const {
if (Matches.size() != 1) return 0;
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 = 0;
if (NumMatches == 0 && Complain) {
if (Resolver.IsInvalidFormOfPointerToMemberFunction())
Resolver.ComplainIsInvalidFormOfPointerToMemberFunction();
else
Resolver.ComplainNoMatchesFound();
}
else if (NumMatches > 1 && Complain)
Resolver.ComplainMultipleMatchesFound();
else if (NumMatches == 1) {
Fn = Resolver.getMatchingFunctionDecl();
assert(Fn);
FoundResult = *Resolver.getMatchingFunctionAccessPair();
if (Complain) {
if (Resolver.IsStaticMemberFunctionFromBoundPointer())
Resolver.ComplainIsStaticMemberFunctionFromBoundPointer();
else
CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
}
}
if (pHadMultipleCandidates)
*pHadMultipleCandidates = Resolver.hadMultipleCandidates();
return Fn;
}
FunctionDecl *
Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
bool Complain,
DeclAccessPair *FoundResult) {
if (!ovl->hasExplicitTemplateArgs())
return 0;
TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
FunctionDecl *Matched = 0;
for (UnresolvedSetIterator I = ovl->decls_begin(),
E = ovl->decls_end(); I != E; ++I) {
FunctionTemplateDecl *FunctionTemplate
= cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl());
FunctionDecl *Specialization = 0;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info,
true)) {
FailedCandidates.addCandidate()
.set(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 0;
}
Matched = Specialization;
if (FoundResult) *FoundResult = I.getPair();
}
if (Matched && getLangOpts().CPlusPlus1y &&
Matched->getReturnType()->isUndeducedType() &&
DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
return 0;
return Matched;
}
bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
ExprResult &SrcExpr, bool doFunctionPointerConverion,
bool complain, const 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()->getLocStart())) {
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 =
Owned(FixOverloadedFunctionReference(SrcExpr.take(), found, fn));
if (doFunctionPointerConverion) {
SingleFunctionExpression =
DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
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;
}
S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false,
PartialOverloading);
return;
}
if (FunctionTemplateDecl *FuncTemplate
= dyn_cast<FunctionTemplateDecl>(Callee)) {
S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,
ExplicitTemplateArgs, Args, CandidateSet);
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 = 0;
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(), false,
ULE->getExprLoc(),
Args, ExplicitTemplateArgs,
CandidateSet, PartialOverloading);
}
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,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args) {
if (SemaRef.ActiveTemplateInstantiations.empty() || !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();
if (isa<CXXRecordDecl>(DC)) {
R.clear();
return false;
}
OverloadCandidateSet Candidates(FnLoc);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
AddOverloadedCallCandidate(SemaRef, I.getPair(),
ExplicitTemplateArgs, Args,
Candidates, false, false);
OverloadCandidateSet::iterator Best;
if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) {
R.clear();
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,
0, 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,
llvm::MutableArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool EmptyLookup, bool AllowTypoCorrection) {
if (SemaRef.IsBuildingRecoveryCallExpr)
return ExprError();
BuildRecoveryCallExprRAII RCE(SemaRef);
CXXScopeSpec SS;
SS.Adopt(ULE->getQualifierLoc());
SourceLocation TemplateKWLoc = ULE->getTemplateKeywordLoc();
TemplateArgumentListInfo TABuffer;
TemplateArgumentListInfo *ExplicitTemplateArgs = 0;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TABuffer);
ExplicitTemplateArgs = &TABuffer;
}
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
FunctionCallFilterCCC Validator(SemaRef, Args.size(),
ExplicitTemplateArgs != 0);
NoTypoCorrectionCCC RejectAll;
CorrectionCandidateCallback *CCC = AllowTypoCorrection ?
(CorrectionCandidateCallback*)&Validator :
(CorrectionCandidateCallback*)&RejectAll;
if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R,
ExplicitTemplateArgs, Args) &&
(!EmptyLookup ||
SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC,
ExplicitTemplateArgs, Args)))
return ExprError();
assert(!R.empty() && "lookup results empty despite recovery");
ExprResult NewFn = ExprError();
if ((*R.begin())->isCXXClassMember())
NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
R, ExplicitTemplateArgs);
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.ActOnCallExpr( 0, NewFn.take(), 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() + 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 (CandidateSet->empty()) {
if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
(isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
CallExpr *CE = new (Context) CallExpr(Context, Fn, Args,
Context.DependentTy, VK_RValue,
RParenLoc);
CE->setTypeDependent(true);
*Result = Owned(CE);
return true;
}
return false;
}
UnbridgedCasts.restore();
return false;
}
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) {
if (CandidateSet->empty())
return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, Args,
RParenLoc, true,
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);
}
case OR_No_Viable_Function: {
ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc,
Args, RParenLoc,
false,
AllowTypoCorrection);
if (!Recovery.isInvalid())
return Recovery;
SemaRef.Diag(Fn->getLocStart(),
diag::err_ovl_no_viable_function_in_call)
<< ULE->getName() << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
break;
}
case OR_Ambiguous:
SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, Args);
break;
case OR_Deleted: {
SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_deleted_call)
<< (*Best)->Function->isDeleted()
<< ULE->getName()
<< SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function)
<< Fn->getSourceRange();
CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args);
FunctionDecl *FDecl = (*Best)->Function;
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
ExecConfig);
}
}
return ExprError();
}
ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn,
UnresolvedLookupExpr *ULE,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc,
Expr *ExecConfig,
bool AllowTypoCorrection) {
OverloadCandidateSet CandidateSet(Fn->getExprLoc());
ExprResult result;
if (buildOverloadedCallSet(S, Fn, ULE, Args, LParenLoc, &CandidateSet,
&result))
return result;
OverloadCandidateSet::iterator Best;
OverloadingResult OverloadResult =
CandidateSet.BestViableFunction(*this, Fn->getLocStart(), 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()));
}
ExprResult
Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
const UnresolvedSetImpl &Fns,
Expr *Input) {
UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
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, 0 };
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 Owned(new (Context) UnaryOperator(Input,
Opc,
Context.DependentTy,
VK_RValue, OK_Ordinary,
OpLoc));
CXXRecordDecl *NamingClass = 0; UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
NestedNameSpecifierLoc(), OpNameInfo,
true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, ArgsArray,
Context.DependentTy,
VK_RValue,
OpLoc, false));
}
OverloadCandidateSet CandidateSet(OpLoc);
AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false);
AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet);
AddArgumentDependentLookupCandidates(OpName, true, OpLoc,
ArgsArray, 0,
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) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
ExprResult InputRes =
PerformObjectArgumentInitialization(Input, 0,
Best->FoundDecl, Method);
if (InputRes.isInvalid())
return ExprError();
Input = InputRes.take();
} else {
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Input);
if (InputInit.isInvalid())
return ExprError();
Input = InputInit.take();
}
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl,
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 =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), ArgsArray,
ResultTy, VK, OpLoc, false);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall, FnDecl))
return ExprError();
return MaybeBindToTemporary(TheCall);
} else {
ExprResult InputRes =
PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0],
Best->Conversions[0], AA_Passing);
if (InputRes.isInvalid())
return ExprError();
Input = InputRes.take();
break;
}
}
case OR_No_Viable_Function:
if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, ArgsArray))
return ExprError();
break;
case OR_Ambiguous:
Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getType()
<< Input->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, ArgsArray,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< UnaryOperator::getOpcodeStr(Opc)
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Input->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, ArgsArray,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
}
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
ExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
unsigned OpcIn,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=0;
BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn);
OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
if (Fns.empty()) {
if (Opc <= BO_Assign || Opc > BO_OrAssign)
return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc,
Context.DependentTy,
VK_RValue, OK_Ordinary,
OpLoc,
FPFeatures.fp_contract));
return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc,
Context.DependentTy,
VK_LValue,
OK_Ordinary,
Context.DependentTy,
Context.DependentTy,
OpLoc,
FPFeatures.fp_contract));
}
CXXRecordDecl *NamingClass = 0; DeclarationNameInfo OpNameInfo(OpName, OpLoc);
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
NestedNameSpecifierLoc(), OpNameInfo,
true, IsOverloaded(Fns),
Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args,
Context.DependentTy, VK_RValue,
OpLoc, FPFeatures.fp_contract));
}
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);
AddFunctionCandidates(Fns, Args, CandidateSet, false);
AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet);
AddArgumentDependentLookupCandidates(OpName, true,
OpLoc, Args,
0,
CandidateSet);
AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) {
case OR_Success: {
FunctionDecl *FnDecl = Best->Function;
if (FnDecl) {
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(), Owned(Args[1]));
if (Arg1.isInvalid())
return ExprError();
ExprResult Arg0 =
PerformObjectArgumentInitialization(Args[0], 0,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
Args[0] = Arg0.takeAs<Expr>();
Args[1] = RHS = Arg1.takeAs<Expr>();
} else {
ExprResult Arg0 = PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(0)),
SourceLocation(), Owned(Args[0]));
if (Arg0.isInvalid())
return ExprError();
ExprResult Arg1 =
PerformCopyInitialization(
InitializedEntity::InitializeParameter(Context,
FnDecl->getParamDecl(1)),
SourceLocation(), Owned(Args[1]));
if (Arg1.isInvalid())
return ExprError();
Args[0] = LHS = Arg0.takeAs<Expr>();
Args[1] = RHS = Arg1.takeAs<Expr>();
}
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
Best->FoundDecl,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
QualType ResultTy = FnDecl->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(),
Args, ResultTy, VK, OpLoc,
FPFeatures.fp_contract);
if (CheckCallReturnType(FnDecl->getReturnType(), OpLoc, TheCall,
FnDecl))
return ExprError();
ArrayRef<const Expr *> ArgsArray(Args, 2);
if (isa<CXXMethodDecl>(FnDecl))
ArgsArray = ArgsArray.slice(1);
checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc,
TheCall->getSourceRange(), VariadicDoesNotApply);
return MaybeBindToTemporary(TheCall);
} else {
ExprResult ArgsRes0 =
PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
Best->Conversions[0], AA_Passing);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.take();
ExprResult ArgsRes1 =
PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
Best->Conversions[1], AA_Passing);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.take();
break;
}
}
case OR_No_Viable_Function: {
if (Opc == BO_Comma)
break;
ExprResult Result = ExprError();
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!");
if (Result.isInvalid())
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
BinaryOperator::getOpcodeStr(Opc), OpLoc);
return Result;
}
case OR_Ambiguous:
Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getType() << Args[1]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args,
BinaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
case OR_Deleted:
if (isImplicitlyDeleted(Best->Function)) {
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
Diag(OpLoc, diag::err_ovl_deleted_special_oper)
<< Context.getRecordType(Method->getParent())
<< getSpecialMember(Method);
NoteDeletedFunction(Method);
return ExprError();
} else {
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
}
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
BinaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
}
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
}
ExprResult
Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
SourceLocation RLoc,
Expr *Base, Expr *Idx) {
Expr *Args[2] = { Base, Idx };
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Subscript);
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
CXXRecordDecl *NamingClass = 0; DeclarationNameInfo OpNameInfo(OpName, LLoc);
OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, NamingClass,
NestedNameSpecifierLoc(), OpNameInfo,
true, false,
UnresolvedSetIterator(),
UnresolvedSetIterator());
return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn,
Args,
Context.DependentTy,
VK_RValue,
RLoc, false));
}
if (checkPlaceholderForOverload(*this, Args[0]))
return ExprError();
if (checkPlaceholderForOverload(*this, Args[1]))
return ExprError();
OverloadCandidateSet CandidateSet(LLoc);
AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, CandidateSet);
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], Args[1], Best->FoundDecl);
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
ExprResult Arg0 =
PerformObjectArgumentInitialization(Args[0], 0,
Best->FoundDecl, Method);
if (Arg0.isInvalid())
return ExprError();
Args[0] = Arg0.take();
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
Context,
FnDecl->getParamDecl(0)),
SourceLocation(),
Owned(Args[1]));
if (InputInit.isInvalid())
return ExprError();
Args[1] = InputInit.takeAs<Expr>();
DeclarationNameInfo OpLocInfo(OpName, LLoc);
OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc));
ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl,
Best->FoundDecl,
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 =
new (Context) CXXOperatorCallExpr(Context, OO_Subscript,
FnExpr.take(), Args,
ResultTy, VK, RLoc,
false);
if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
return ExprError();
return MaybeBindToTemporary(TheCall);
} else {
ExprResult ArgsRes0 =
PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0],
Best->Conversions[0], AA_Passing);
if (ArgsRes0.isInvalid())
return ExprError();
Args[0] = ArgsRes0.take();
ExprResult ArgsRes1 =
PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1],
Best->Conversions[1], AA_Passing);
if (ArgsRes1.isInvalid())
return ExprError();
Args[1] = ArgsRes1.take();
break;
}
}
case OR_No_Viable_Function: {
if (CandidateSet.empty())
Diag(LLoc, diag::err_ovl_no_oper)
<< Args[0]->getType() << 0
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
else
Diag(LLoc, diag::err_ovl_no_viable_subscript)
<< Args[0]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args,
"[]", LLoc);
return ExprError();
}
case OR_Ambiguous:
Diag(LLoc, diag::err_ovl_ambiguous_oper_binary)
<< "[]"
<< Args[0]->getType() << Args[1]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args,
"[]", LLoc);
return ExprError();
case OR_Deleted:
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
CandidateSet.NoteCandidates(*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) {
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 = Qualifiers::fromCVRMask(proto->getTypeQuals());
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
= new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
resultType, valueKind, RParenLoc);
if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getLocStart(),
call, 0))
return ExprError();
if (ConvertArgumentsForCall(call, op, 0, proto, Args, RParenLoc))
return ExprError();
if (CheckOtherCall(call, proto))
return ExprError();
return MaybeBindToTemporary(call);
}
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
NestedNameSpecifier *Qualifier = 0;
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());
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
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);
} 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;
switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
return ExprError();
if (Method != FoundDecl.getDecl() &&
DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
return ExprError();
break;
case OR_No_Viable_Function:
Diag(UnresExpr->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
return ExprError();
case OR_Ambiguous:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
return ExprError();
case OR_Deleted:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName
<< getDeletedOrUnavailableSuffix(Best->Function)
<< MemExprE->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
return ExprError();
}
MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
if (Method->isStatic()) {
return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, Args,
RParenLoc);
}
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?");
CXXMemberCallExpr *TheCall =
new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
ResultType, VK, RParenLoc);
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
return ExprError();
if (!Method->isStatic()) {
ExprResult ObjectArg =
PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier,
FoundDecl, Method);
if (ObjectArg.isInvalid())
return ExprError();
MemExpr->setBase(ObjectArg.take());
}
const FunctionProtoType *Proto =
Method->getType()->getAs<FunctionProtoType>();
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
return ExprError();
DiagnoseSentinelCalls(Method, LParenLoc, Args);
if (CheckFunctionCall(Method, TheCall, Proto))
return ExprError();
if ((isa<CXXConstructorDecl>(CurContext) ||
isa<CXXDestructorDecl>(CurContext)) &&
TheCall->getMethodDecl()->isPure()) {
const CXXMethodDecl *MD = TheCall->getMethodDecl();
if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) {
Diag(MemExpr->getLocStart(),
diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor)
<< MD->getDeclName() << isa<CXXDestructorDecl>(CurContext)
<< MD->getParent()->getDeclName();
Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName();
}
}
return MaybeBindToTemporary(TheCall);
}
ExprResult
Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation RParenLoc) {
if (checkPlaceholderForOverload(*this, Obj))
return ExprError();
ExprResult Object = Owned(Obj);
UnbridgedCastsSet UnbridgedCasts;
if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts))
return ExprError();
assert(Object.get()->getType()->isRecordType() && "Requires object type argument");
const RecordType *Record = Object.get()->getType()->getAs<RecordType>();
OverloadCandidateSet CandidateSet(LParenLoc);
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call);
if (RequireCompleteType(LParenLoc, Object.get()->getType(),
diag::err_incomplete_object_call, Object.get()))
return true;
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);
}
std::pair<CXXRecordDecl::conversion_iterator,
CXXRecordDecl::conversion_iterator> Conversions
= cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions();
for (CXXRecordDecl::conversion_iterator
I = Conversions.first, E = Conversions.second; 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()->getLocStart(),
Best)) {
case OR_Success:
break;
case OR_No_Viable_Function:
if (CandidateSet.empty())
Diag(Object.get()->getLocStart(), diag::err_ovl_no_oper)
<< Object.get()->getType() << 1
<< Object.get()->getSourceRange();
else
Diag(Object.get()->getLocStart(),
diag::err_ovl_no_viable_object_call)
<< Object.get()->getType() << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
break;
case OR_Ambiguous:
Diag(Object.get()->getLocStart(),
diag::err_ovl_ambiguous_object_call)
<< Object.get()->getType() << Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args);
break;
case OR_Deleted:
Diag(Object.get()->getLocStart(),
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
<< Object.get()->getType()
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Object.get()->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
break;
}
if (Best == CandidateSet.end())
return true;
UnbridgedCasts.restore();
if (Best->Function == 0) {
CXXConversionDecl *Conv
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, 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 = Owned(ImplicitCastExpr::Create(Context, Call.get()->getType(),
CK_UserDefinedConversion,
Call.get(), 0, VK_RValue));
return ActOnCallExpr(S, Call.get(), LParenLoc, Args, RParenLoc);
}
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
if (Method->isInvalidDecl())
return ExprError();
const FunctionProtoType *Proto =
Method->getType()->getAs<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,
HadMultipleCandidates,
OpLocInfo.getLoc(),
OpLocInfo.getInfo());
if (NewFn.isInvalid())
return true;
llvm::OwningArrayPtr<Expr *> MethodArgs(new Expr*[Args.size() + 1]);
MethodArgs[0] = Object.get();
std::copy(Args.begin(), Args.end(), &MethodArgs[1]);
QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall = new (Context)
CXXOperatorCallExpr(Context, OO_Call, NewFn.take(),
llvm::makeArrayRef(MethodArgs.get(), Args.size() + 1),
ResultTy, VK, RParenLoc, false);
MethodArgs.reset();
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
return true;
if (Args.size() < NumParams)
TheCall->setNumArgs(Context, NumParams + 1);
bool IsError = false;
ExprResult ObjRes =
PerformObjectArgumentInitialization(Object.get(), 0,
Best->FoundDecl, Method);
if (ObjRes.isInvalid())
IsError = true;
else
Object = ObjRes;
TheCall->setArg(0, Object.take());
for (unsigned i = 0; i != NumParams; i++) {
Expr *Arg;
if (i < Args.size()) {
Arg = Args[i];
ExprResult InputInit
= PerformCopyInitialization(InitializedEntity::InitializeParameter(
Context,
Method->getParamDecl(i)),
SourceLocation(), Arg);
IsError |= InputInit.isInvalid();
Arg = InputInit.takeAs<Expr>();
} else {
ExprResult DefArg
= BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i));
if (DefArg.isInvalid()) {
IsError = true;
break;
}
Arg = DefArg.takeAs<Expr>();
}
TheCall->setArg(i + 1, Arg);
}
if (Proto->isVariadic()) {
for (unsigned i = NumParams, e = Args.size(); i < e; i++) {
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0);
IsError |= Arg.isInvalid();
TheCall->setArg(i + 1, Arg.take());
}
}
if (IsError) return true;
DiagnoseSentinelCalls(Method, LParenLoc, Args);
if (CheckFunctionCall(Method, TheCall, Proto))
return true;
return MaybeBindToTemporary(TheCall);
}
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);
const RecordType *BaseRecord = Base->getType()->getAs<RecordType>();
if (RequireCompleteType(Loc, Base->getType(),
diag::err_typecheck_incomplete_tag, Base))
return ExprError();
LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName);
LookupQualifiedName(R, BaseRecord->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:
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, OCD_AllCandidates, Base);
return ExprError();
case OR_Ambiguous:
Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary)
<< "->" << Base->getType() << Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Base);
return ExprError();
case OR_Deleted:
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< "->"
<< getDeletedOrUnavailableSuffix(Best->Function)
<< Base->getSourceRange();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base);
return ExprError();
}
CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
ExprResult BaseResult =
PerformObjectArgumentInitialization(Base, 0,
Best->FoundDecl, Method);
if (BaseResult.isInvalid())
return ExprError();
Base = BaseResult.take();
ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl,
HadMultipleCandidates, OpLoc);
if (FnExpr.isInvalid())
return ExprError();
QualType ResultTy = Method->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
CXXOperatorCallExpr *TheCall =
new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(),
Base, ResultTy, VK, OpLoc, false);
if (CheckCallReturnType(Method->getReturnType(), OpLoc, TheCall, Method))
return ExprError();
return MaybeBindToTemporary(TheCall);
}
ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R,
DeclarationNameInfo &SuffixInfo,
ArrayRef<Expr*> Args,
SourceLocation LitEndLoc,
TemplateArgumentListInfo *TemplateArgs) {
SourceLocation UDSuffixLoc = SuffixInfo.getCXXLiteralOperatorNameLoc();
OverloadCandidateSet CandidateSet(UDSuffixLoc);
AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true,
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:
Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call)
<< R.getLookupName();
CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args);
return ExprError();
case OR_Ambiguous:
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args);
return ExprError();
}
FunctionDecl *FD = Best->Function;
ExprResult Fn = CreateFunctionRefExpr(*this, FD, Best->FoundDecl,
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.take();
}
QualType ResultTy = FD->getReturnType();
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
ResultTy = ResultTy.getNonLValueExprType(Context);
UserDefinedLiteral *UDL =
new (Context) UserDefinedLiteral(Context, Fn.take(),
llvm::makeArrayRef(ConvArgs, Args.size()),
ResultTy, VK, LitEndLoc, UDSuffixLoc);
if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD))
return ExprError();
if (CheckFunctionCall(FD, UDL, NULL))
return ExprError();
return MaybeBindToTemporary(UDL);
}
Sema::ForRangeStatus
Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc,
SourceLocation RangeLoc, VarDecl *Decl,
BeginEndFunction BEF,
const DeclarationNameInfo &NameInfo,
LookupResult &MemberLookup,
OverloadCandidateSet *CandidateSet,
Expr *Range, ExprResult *CallExpr) {
CandidateSet->clear();
if (!MemberLookup.empty()) {
ExprResult MemberRef =
BuildMemberReferenceExpr(Range, Range->getType(), Loc,
false, CXXScopeSpec(),
SourceLocation(),
0,
MemberLookup,
0);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
<< RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
*CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, None, Loc, 0);
if (CallExpr->isInvalid()) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
<< RangeLoc << BEF << Range->getType();
return FRS_DiagnosticIssued;
}
} else {
UnresolvedSet<0> FoundNames;
UnresolvedLookupExpr *Fn =
UnresolvedLookupExpr::Create(Context, 0,
NestedNameSpecifierLoc(), NameInfo,
true, false,
FoundNames.begin(), FoundNames.end());
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->getLocStart(), Best);
if (OverloadResult == OR_No_Viable_Function) {
*CallExpr = ExprError();
return FRS_NoViableFunction;
}
*CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, Range,
Loc, 0, CandidateSet, &Best,
OverloadResult,
false);
if (CallExpr->isInvalid() || OverloadResult != OR_Success) {
*CallExpr = ExprError();
Diag(Range->getLocStart(), diag::note_in_for_range)
<< RangeLoc << BEF << Range->getType();
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, 0,
ICE->getValueKind());
}
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());
return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType,
VK_RValue, OK_Ordinary,
UnOp->getOperatorLoc());
}
}
Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
Found, Fn);
if (SubExpr == UnOp->getSubExpr())
return UnOp;
return new (Context) UnaryOperator(SubExpr, UO_AddrOf,
Context.getPointerType(SubExpr->getType()),
VK_RValue, OK_Ordinary,
UnOp->getOperatorLoc());
}
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
if (ULE->hasExplicitTemplateArgs()) {
ULE->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
}
DeclRefExpr *DRE = DeclRefExpr::Create(Context,
ULE->getQualifierLoc(),
ULE->getTemplateKeywordLoc(),
Fn,
false, ULE->getNameLoc(),
Fn->getType(),
VK_LValue,
Found.getDecl(),
TemplateArgs);
MarkDeclRefReferenced(DRE);
DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
return DRE;
}
if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0;
if (MemExpr->hasExplicitTemplateArgs()) {
MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
}
Expr *Base;
if (MemExpr->isImplicitAccess()) {
if (cast<CXXMethodDecl>(Fn)->isStatic()) {
DeclRefExpr *DRE = DeclRefExpr::Create(Context,
MemExpr->getQualifierLoc(),
MemExpr->getTemplateKeywordLoc(),
Fn,
false,
MemExpr->getMemberLoc(),
Fn->getType(),
VK_LValue,
Found.getDecl(),
TemplateArgs);
MarkDeclRefReferenced(DRE);
DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
return DRE;
} else {
SourceLocation Loc = MemExpr->getMemberLoc();
if (MemExpr->getQualifier())
Loc = MemExpr->getQualifierLoc().getBeginLoc();
CheckCXXThisCapture(Loc);
Base = new (Context) CXXThisExpr(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_RValue;
type = Context.BoundMemberTy;
}
MemberExpr *ME = MemberExpr::Create(Context, Base,
MemExpr->isArrow(),
MemExpr->getQualifierLoc(),
MemExpr->getTemplateKeywordLoc(),
Fn,
Found,
MemExpr->getMemberNameInfo(),
TemplateArgs,
type, valueKind, OK_Ordinary);
ME->setHadMultipleCandidates(true);
MarkMemberReferenced(ME);
return ME;
}
llvm_unreachable("Invalid reference to overloaded function");
}
ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
DeclAccessPair Found,
FunctionDecl *Fn) {
return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
}
}