зеркало из https://github.com/microsoft/clang.git
Handle the resolution of a reference to a function template (which
includes explicitly-specified template arguments) to a function template specialization in cases where no deduction is performed or deduction fails. Patch by Faisal Vali, fixes PR7505! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126048 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6c94837815
Коммит
1be8eec3dd
|
@ -2686,6 +2686,10 @@ def err_bad_reinterpret_cast_overload : Error<
|
||||||
def err_bad_static_cast_overload : Error<
|
def err_bad_static_cast_overload : Error<
|
||||||
"address of overloaded function %0 cannot be static_cast to type %1">;
|
"address of overloaded function %0 cannot be static_cast to type %1">;
|
||||||
|
|
||||||
|
def err_bad_cstyle_cast_overload : Error<
|
||||||
|
"address of overloaded function %0 cannot be cast to type %1">;
|
||||||
|
|
||||||
|
|
||||||
def err_bad_cxx_cast_generic : Error<
|
def err_bad_cxx_cast_generic : Error<
|
||||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||||
"functional-style cast}0 from %1 to %2 is not allowed">;
|
"functional-style cast}0 from %1 to %2 is not allowed">;
|
||||||
|
|
|
@ -1247,12 +1247,28 @@ public:
|
||||||
OverloadCandidateSet& CandidateSet,
|
OverloadCandidateSet& CandidateSet,
|
||||||
bool PartialOverloading = false);
|
bool PartialOverloading = false);
|
||||||
|
|
||||||
|
// Emit as a 'note' the specific overload candidate
|
||||||
void NoteOverloadCandidate(FunctionDecl *Fn);
|
void NoteOverloadCandidate(FunctionDecl *Fn);
|
||||||
|
|
||||||
|
// Emit as a series of 'note's all template and non-templates
|
||||||
|
// identified by the expression Expr
|
||||||
|
void NoteAllOverloadCandidates(Expr* E);
|
||||||
|
|
||||||
|
// [PossiblyAFunctionType] --> [Return]
|
||||||
|
// NonFunctionType --> NonFunctionType
|
||||||
|
// R (A) --> R(A)
|
||||||
|
// R (*)(A) --> R (A)
|
||||||
|
// R (&)(A) --> R (A)
|
||||||
|
// R (S::*)(A) --> R (A)
|
||||||
|
QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
|
||||||
|
|
||||||
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
|
||||||
bool Complain,
|
bool Complain,
|
||||||
DeclAccessPair &Found);
|
DeclAccessPair &Found);
|
||||||
FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
|
|
||||||
|
FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From,
|
||||||
|
bool Complain = false,
|
||||||
|
DeclAccessPair* Found = 0);
|
||||||
|
|
||||||
Expr *FixOverloadedFunctionReference(Expr *E,
|
Expr *FixOverloadedFunctionReference(Expr *E,
|
||||||
DeclAccessPair FoundDecl,
|
DeclAccessPair FoundDecl,
|
||||||
|
@ -3702,7 +3718,8 @@ public:
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
const PartialDiagnostic &NoneDiag,
|
const PartialDiagnostic &NoneDiag,
|
||||||
const PartialDiagnostic &AmbigDiag,
|
const PartialDiagnostic &AmbigDiag,
|
||||||
const PartialDiagnostic &CandidateDiag);
|
const PartialDiagnostic &CandidateDiag,
|
||||||
|
bool Complain = true);
|
||||||
|
|
||||||
ClassTemplatePartialSpecializationDecl *
|
ClassTemplatePartialSpecializationDecl *
|
||||||
getMoreSpecializedPartialSpecialization(
|
getMoreSpecializedPartialSpecialization(
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
|
|
||||||
static void NoteAllOverloadCandidates(Expr* const Expr, Sema& sema);
|
|
||||||
|
|
||||||
enum TryCastResult {
|
enum TryCastResult {
|
||||||
TC_NotApplicable, ///< The cast method is not applicable.
|
TC_NotApplicable, ///< The cast method is not applicable.
|
||||||
|
@ -122,12 +121,24 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
|
||||||
CXXCastPath &BasePath);
|
CXXCastPath &BasePath);
|
||||||
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
||||||
bool CStyle, unsigned &msg);
|
bool CStyle, unsigned &msg);
|
||||||
static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
|
static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
|
||||||
QualType DestType, bool CStyle,
|
QualType DestType, bool CStyle,
|
||||||
const SourceRange &OpRange,
|
const SourceRange &OpRange,
|
||||||
unsigned &msg,
|
unsigned &msg,
|
||||||
CastKind &Kind);
|
CastKind &Kind);
|
||||||
|
|
||||||
|
|
||||||
|
static ExprResult
|
||||||
|
ResolveAndFixSingleFunctionTemplateSpecialization(
|
||||||
|
Sema &Self, Expr *SrcExpr,
|
||||||
|
bool DoFunctionPointerConverion = false,
|
||||||
|
bool Complain = false,
|
||||||
|
const SourceRange& OpRangeForComplaining = SourceRange(),
|
||||||
|
QualType DestTypeForComplaining = QualType(),
|
||||||
|
unsigned DiagIDForComplaining = 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
|
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
|
||||||
ExprResult
|
ExprResult
|
||||||
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
||||||
|
@ -583,7 +594,7 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
||||||
Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
|
Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
|
||||||
<< OverloadExpr::find(SrcExpr).Expression->getName()
|
<< OverloadExpr::find(SrcExpr).Expression->getName()
|
||||||
<< DestType << OpRange;
|
<< DestType << OpRange;
|
||||||
NoteAllOverloadCandidates(SrcExpr, Self);
|
Self.NoteAllOverloadCandidates(SrcExpr);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType);
|
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType);
|
||||||
|
@ -604,7 +615,20 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
||||||
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
||||||
if (DestType->isVoidType()) {
|
if (DestType->isVoidType()) {
|
||||||
Self.IgnoredValueConversions(SrcExpr);
|
Self.IgnoredValueConversions(SrcExpr);
|
||||||
Kind = CK_ToVoid;
|
if (SrcExpr->getType() == Self.Context.OverloadTy) {
|
||||||
|
ExprResult SingleFunctionExpression =
|
||||||
|
ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr,
|
||||||
|
false, // Decay Function to ptr
|
||||||
|
true, // Complain
|
||||||
|
OpRange, DestType, diag::err_bad_static_cast_overload);
|
||||||
|
if (SingleFunctionExpression.isUsable())
|
||||||
|
{
|
||||||
|
SrcExpr = SingleFunctionExpression.release();
|
||||||
|
Kind = CK_ToVoid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Kind = CK_ToVoid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,13 +638,12 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
||||||
|
|
||||||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||||
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
|
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
|
||||||
Kind, BasePath) != TC_Success && msg != 0)
|
Kind, BasePath) != TC_Success && msg != 0) {
|
||||||
{
|
|
||||||
if (SrcExpr->getType() == Self.Context.OverloadTy) {
|
if (SrcExpr->getType() == Self.Context.OverloadTy) {
|
||||||
OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
|
OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
|
||||||
Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
|
Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
|
||||||
<< oe->getName() << DestType << OpRange << oe->getQualifierRange();
|
<< oe->getName() << DestType << OpRange << oe->getQualifierRange();
|
||||||
NoteAllOverloadCandidates(SrcExpr, Self);
|
Self.NoteAllOverloadCandidates(SrcExpr);
|
||||||
} else {
|
} else {
|
||||||
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType);
|
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType);
|
||||||
}
|
}
|
||||||
|
@ -1236,32 +1259,44 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
||||||
return TC_Success;
|
return TC_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A helper function to resolve and fix an overloaded expression that
|
||||||
static void NoteAllOverloadCandidates(Expr* const Expr, Sema& sema)
|
// can be resolved because it identifies a single function
|
||||||
{
|
// template specialization
|
||||||
|
// Last three arguments should only be supplied if Complain = true
|
||||||
assert(Expr->getType() == sema.Context.OverloadTy);
|
static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization(
|
||||||
|
Sema &Self, Expr *SrcExpr,
|
||||||
OverloadExpr::FindResult Ovl = OverloadExpr::find(Expr);
|
bool DoFunctionPointerConverion,
|
||||||
OverloadExpr *const OvlExpr = Ovl.Expression;
|
bool Complain,
|
||||||
|
const SourceRange& OpRangeForComplaining,
|
||||||
for (UnresolvedSetIterator it = OvlExpr->decls_begin(),
|
QualType DestTypeForComplaining,
|
||||||
end = OvlExpr->decls_end(); it != end; ++it) {
|
unsigned DiagIDForComplaining) {
|
||||||
if ( FunctionTemplateDecl *ftd =
|
assert(SrcExpr->getType() == Self.Context.OverloadTy);
|
||||||
dyn_cast<FunctionTemplateDecl>((*it)->getUnderlyingDecl()) )
|
DeclAccessPair Found;
|
||||||
{
|
bool ret = false;
|
||||||
sema.NoteOverloadCandidate(ftd->getTemplatedDecl());
|
Expr* SingleFunctionExpression = 0;
|
||||||
}
|
if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization(
|
||||||
else if ( FunctionDecl *f =
|
SrcExpr, false, // false -> Complain
|
||||||
dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl()) )
|
&Found)) {
|
||||||
{
|
if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
|
||||||
sema.NoteOverloadCandidate(f);
|
// mark the expression as resolved to Fn
|
||||||
}
|
SingleFunctionExpression = Self.FixOverloadedFunctionReference(SrcExpr,
|
||||||
|
Found, Fn);
|
||||||
|
|
||||||
|
if (DoFunctionPointerConverion)
|
||||||
|
Self.DefaultFunctionArrayLvalueConversion(SingleFunctionExpression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (!SingleFunctionExpression && Complain) {
|
||||||
|
OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
|
||||||
|
Self.Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
|
||||||
|
<< oe->getName() << DestTypeForComplaining << OpRangeForComplaining
|
||||||
|
<< oe->getQualifierRange();
|
||||||
|
Self.NoteAllOverloadCandidates(SrcExpr);
|
||||||
|
}
|
||||||
|
return SingleFunctionExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
|
||||||
static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
|
|
||||||
QualType DestType, bool CStyle,
|
QualType DestType, bool CStyle,
|
||||||
const SourceRange &OpRange,
|
const SourceRange &OpRange,
|
||||||
unsigned &msg,
|
unsigned &msg,
|
||||||
|
@ -1272,9 +1307,20 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
|
||||||
QualType SrcType = SrcExpr->getType();
|
QualType SrcType = SrcExpr->getType();
|
||||||
|
|
||||||
// Is the source an overloaded name? (i.e. &foo)
|
// Is the source an overloaded name? (i.e. &foo)
|
||||||
// If so, reinterpret_cast can not help us here (13.4, p1, bullet 5)
|
// If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ...
|
||||||
if (SrcType == Self.Context.OverloadTy)
|
if (SrcType == Self.Context.OverloadTy) {
|
||||||
return TC_NotApplicable;
|
// ... unless foo<int> resolves to an lvalue unambiguously
|
||||||
|
ExprResult SingleFunctionExpr =
|
||||||
|
ResolveAndFixSingleFunctionTemplateSpecialization(Self, SrcExpr,
|
||||||
|
Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr
|
||||||
|
);
|
||||||
|
if (SingleFunctionExpr.isUsable()) {
|
||||||
|
SrcExpr = SingleFunctionExpr.release();
|
||||||
|
SrcType = SrcExpr->getType();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return TC_NotApplicable;
|
||||||
|
}
|
||||||
|
|
||||||
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
|
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
|
||||||
bool LValue = DestTypeTmp->isLValueReferenceType();
|
bool LValue = DestTypeTmp->isLValueReferenceType();
|
||||||
|
@ -1495,8 +1541,24 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
||||||
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
||||||
if (CastTy->isVoidType()) {
|
if (CastTy->isVoidType()) {
|
||||||
IgnoredValueConversions(CastExpr);
|
IgnoredValueConversions(CastExpr);
|
||||||
Kind = CK_ToVoid;
|
bool ret = false; // false is 'able to convert'
|
||||||
return false;
|
if (CastExpr->getType() == Context.OverloadTy) {
|
||||||
|
ExprResult SingleFunctionExpr =
|
||||||
|
ResolveAndFixSingleFunctionTemplateSpecialization(*this,
|
||||||
|
CastExpr,
|
||||||
|
/* Decay Function to ptr */ false,
|
||||||
|
/* Complain */ true,
|
||||||
|
R, CastTy, diag::err_bad_cstyle_cast_overload);
|
||||||
|
if (SingleFunctionExpr.isUsable()) {
|
||||||
|
CastExpr = SingleFunctionExpr.release();
|
||||||
|
Kind = CK_ToVoid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Kind = CK_ToVoid;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we determine the value kind before we bail out for
|
// Make sure we determine the value kind before we bail out for
|
||||||
|
@ -1547,7 +1609,9 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
||||||
CastTy,
|
CastTy,
|
||||||
/* Complain */ true,
|
/* Complain */ true,
|
||||||
Found);
|
Found);
|
||||||
assert(!Fn && "cast failed but able to resolve overload expression!!");
|
|
||||||
|
assert(!Fn
|
||||||
|
&& "cast failed but able to resolve overload expression!!");
|
||||||
(void)Fn;
|
(void)Fn;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3190,7 +3190,10 @@ InitializationSequence::InitializationSequence(Sema &S,
|
||||||
/*InOverloadResolution*/ false,
|
/*InOverloadResolution*/ false,
|
||||||
/*CStyle=*/Kind.isCStyleOrFunctionalCast()))
|
/*CStyle=*/Kind.isCStyleOrFunctionalCast()))
|
||||||
{
|
{
|
||||||
if (Initializer->getType() == Context.OverloadTy)
|
DeclAccessPair dap;
|
||||||
|
if (Initializer->getType() == Context.OverloadTy &&
|
||||||
|
!S.ResolveAddressOfOverloadedFunction(Initializer
|
||||||
|
, DestType, false, dap))
|
||||||
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
|
SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
|
||||||
else
|
else
|
||||||
SetFailed(InitializationSequence::FK_ConversionFailed);
|
SetFailed(InitializationSequence::FK_ConversionFailed);
|
||||||
|
@ -4161,15 +4164,16 @@ bool InitializationSequence::Diagnose(Sema &S,
|
||||||
<< Args[0]->getSourceRange();
|
<< Args[0]->getSourceRange();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FK_ConversionFailed:
|
case FK_ConversionFailed: {
|
||||||
|
QualType FromType = Args[0]->getType();
|
||||||
S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
|
S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
|
||||||
<< (int)Entity.getKind()
|
<< (int)Entity.getKind()
|
||||||
<< DestType
|
<< DestType
|
||||||
<< Args[0]->isLValue()
|
<< Args[0]->isLValue()
|
||||||
<< Args[0]->getType()
|
<< FromType
|
||||||
<< Args[0]->getSourceRange();
|
<< Args[0]->getSourceRange();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case FK_TooManyInitsForScalar: {
|
case FK_TooManyInitsForScalar: {
|
||||||
SourceRange R;
|
SourceRange R;
|
||||||
|
|
||||||
|
|
|
@ -1036,6 +1036,21 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
|
||||||
// We were able to resolve the address of the overloaded function,
|
// We were able to resolve the address of the overloaded function,
|
||||||
// so we can convert to the type of that function.
|
// so we can convert to the type of that function.
|
||||||
FromType = Fn->getType();
|
FromType = Fn->getType();
|
||||||
|
|
||||||
|
// we can sometimes resolve &foo<int> regardless of ToType, so check
|
||||||
|
// if the type matches (identity) or we are converting to bool
|
||||||
|
if (!S.Context.hasSameUnqualifiedType(
|
||||||
|
S.ExtractUnqualifiedFunctionType(ToType), FromType)) {
|
||||||
|
QualType resultTy;
|
||||||
|
// if the function type matches except for [[noreturn]], it's ok
|
||||||
|
if (!IsNoReturnConversion(S.Context, FromType,
|
||||||
|
S.ExtractUnqualifiedFunctionType(ToType), resultTy))
|
||||||
|
// otherwise, only a boolean conversion is standard
|
||||||
|
if (!ToType->isBooleanType())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
|
||||||
if (!Method->isStatic()) {
|
if (!Method->isStatic()) {
|
||||||
const Type *ClassType
|
const Type *ClassType
|
||||||
|
@ -6349,6 +6364,27 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
|
||||||
MaybeEmitInheritedConstructorNote(*this, Fn);
|
MaybeEmitInheritedConstructorNote(*this, Fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Notes the location of all overload candidates designated through
|
||||||
|
// OverloadedExpr
|
||||||
|
void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) {
|
||||||
|
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());
|
||||||
|
} else if (FunctionDecl *Fun
|
||||||
|
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
|
||||||
|
NoteOverloadCandidate(Fun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Diagnoses an ambiguous conversion. The partial diagnostic is the
|
/// Diagnoses an ambiguous conversion. The partial diagnostic is the
|
||||||
/// "lead" diagnostic; it will be given two arguments, the source and
|
/// "lead" diagnostic; it will be given two arguments, the source and
|
||||||
/// target types of the conversion.
|
/// target types of the conversion.
|
||||||
|
@ -7049,186 +7085,207 @@ static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
|
||||||
return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
|
return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
|
|
||||||
/// an overloaded function (C++ [over.over]), where @p From is an
|
|
||||||
/// expression with overloaded function type and @p ToType is the type
|
|
||||||
/// we're trying to resolve to. For example:
|
// [PossiblyAFunctionType] --> [Return]
|
||||||
///
|
// NonFunctionType --> NonFunctionType
|
||||||
/// @code
|
// R (A) --> R(A)
|
||||||
/// int f(double);
|
// R (*)(A) --> R (A)
|
||||||
/// int f(int);
|
// R (&)(A) --> R (A)
|
||||||
///
|
// R (S::*)(A) --> R (A)
|
||||||
/// int (*pfd)(double) = f; // selects f(double)
|
QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
|
||||||
/// @endcode
|
QualType Ret = PossiblyAFunctionType;
|
||||||
///
|
if (const PointerType *ToTypePtr =
|
||||||
/// This routine returns the resulting FunctionDecl if it could be
|
PossiblyAFunctionType->getAs<PointerType>())
|
||||||
/// resolved, and NULL otherwise. When @p Complain is true, this
|
Ret = ToTypePtr->getPointeeType();
|
||||||
/// routine will emit diagnostics if there is an error.
|
else if (const ReferenceType *ToTypeRef =
|
||||||
FunctionDecl *
|
PossiblyAFunctionType->getAs<ReferenceType>())
|
||||||
Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
Ret = ToTypeRef->getPointeeType();
|
||||||
bool Complain,
|
|
||||||
DeclAccessPair &FoundResult) {
|
|
||||||
QualType FunctionType = ToType;
|
|
||||||
bool IsMember = false;
|
|
||||||
if (const PointerType *ToTypePtr = ToType->getAs<PointerType>())
|
|
||||||
FunctionType = ToTypePtr->getPointeeType();
|
|
||||||
else if (const ReferenceType *ToTypeRef = ToType->getAs<ReferenceType>())
|
|
||||||
FunctionType = ToTypeRef->getPointeeType();
|
|
||||||
else if (const MemberPointerType *MemTypePtr =
|
else if (const MemberPointerType *MemTypePtr =
|
||||||
ToType->getAs<MemberPointerType>()) {
|
PossiblyAFunctionType->getAs<MemberPointerType>())
|
||||||
FunctionType = MemTypePtr->getPointeeType();
|
Ret = MemTypePtr->getPointeeType();
|
||||||
IsMember = true;
|
Ret =
|
||||||
}
|
Context.getCanonicalType(Ret).getUnqualifiedType();
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
// C++ [over.over]p1:
|
// A helper class to help with address of function resolution
|
||||||
// [...] [Note: any redundant set of parentheses surrounding the
|
// - allows us to avoid passing around all those ugly parameters
|
||||||
// overloaded function name is ignored (5.1). ]
|
class AddressOfFunctionResolver
|
||||||
// C++ [over.over]p1:
|
{
|
||||||
// [...] The overloaded function name can be preceded by the &
|
Sema& S;
|
||||||
// operator.
|
Expr* SourceExpr;
|
||||||
// However, remember whether the expression has member-pointer form:
|
const QualType& TargetType;
|
||||||
// C++ [expr.unary.op]p4:
|
QualType TargetFunctionType; // Extracted function type from target type
|
||||||
// A pointer to member is only formed when an explicit & is used
|
|
||||||
// and its operand is a qualified-id not enclosed in
|
bool Complain;
|
||||||
// parentheses.
|
//DeclAccessPair& ResultFunctionAccessPair;
|
||||||
OverloadExpr::FindResult Ovl = OverloadExpr::find(From);
|
ASTContext& Context;
|
||||||
OverloadExpr *OvlExpr = Ovl.Expression;
|
|
||||||
|
|
||||||
// We expect a pointer or reference to function, or a function pointer.
|
bool TargetTypeIsNonStaticMemberFunction;
|
||||||
FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
|
bool FoundNonTemplateFunction;
|
||||||
if (!FunctionType->isFunctionType()) {
|
|
||||||
if (Complain)
|
|
||||||
Diag(From->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
|
|
||||||
<< OvlExpr->getName() << ToType;
|
|
||||||
|
|
||||||
return 0;
|
OverloadExpr::FindResult OvlExprInfo;
|
||||||
}
|
OverloadExpr *OvlExpr;
|
||||||
|
TemplateArgumentListInfo OvlExplicitTemplateArgs;
|
||||||
// If the overload expression doesn't have the form of a pointer to
|
|
||||||
// member, don't try to convert it to a pointer-to-member type.
|
|
||||||
if (IsMember && !Ovl.HasFormOfMemberPointer) {
|
|
||||||
if (!Complain) return 0;
|
|
||||||
|
|
||||||
// TODO: Should we condition this on whether any functions might
|
|
||||||
// have matched, or is it more appropriate to do that in callers?
|
|
||||||
// TODO: a fixit wouldn't hurt.
|
|
||||||
Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
|
|
||||||
<< ToType << OvlExpr->getSourceRange();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
|
|
||||||
if (OvlExpr->hasExplicitTemplateArgs()) {
|
|
||||||
OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
|
|
||||||
ExplicitTemplateArgs = &ETABuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(From->getType() == Context.OverloadTy);
|
|
||||||
|
|
||||||
// Look through all of the overloaded functions, searching for one
|
|
||||||
// whose type matches exactly.
|
|
||||||
llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
|
llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
|
||||||
llvm::SmallVector<FunctionDecl *, 4> NonMatches;
|
|
||||||
|
|
||||||
bool FoundNonTemplateFunction = false;
|
public:
|
||||||
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
|
AddressOfFunctionResolver(Sema &S, Expr* SourceExpr,
|
||||||
E = OvlExpr->decls_end(); I != E; ++I) {
|
const QualType& TargetType, bool Complain)
|
||||||
// Look through any using declarations to find the underlying function.
|
: S(S), SourceExpr(SourceExpr), TargetType(TargetType),
|
||||||
NamedDecl *Fn = (*I)->getUnderlyingDecl();
|
Complain(Complain), Context(S.getASTContext()),
|
||||||
|
TargetTypeIsNonStaticMemberFunction(
|
||||||
// C++ [over.over]p3:
|
!!TargetType->getAs<MemberPointerType>()),
|
||||||
// Non-member functions and static member functions match
|
FoundNonTemplateFunction(false),
|
||||||
// targets of type "pointer-to-function" or "reference-to-function."
|
OvlExprInfo(OverloadExpr::find(SourceExpr)),
|
||||||
// Nonstatic member functions match targets of
|
OvlExpr(OvlExprInfo.Expression)
|
||||||
// type "pointer-to-member-function."
|
{
|
||||||
// Note that according to DR 247, the containing class does not matter.
|
ExtractUnqualifiedFunctionTypeFromTargetType();
|
||||||
|
|
||||||
if (FunctionTemplateDecl *FunctionTemplate
|
if (!TargetFunctionType->isFunctionType()) {
|
||||||
= dyn_cast<FunctionTemplateDecl>(Fn)) {
|
if (OvlExpr->hasExplicitTemplateArgs()) {
|
||||||
if (CXXMethodDecl *Method
|
DeclAccessPair dap;
|
||||||
= dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
|
if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
|
||||||
// Skip non-static function templates when converting to pointer, and
|
OvlExpr, false, &dap) ) {
|
||||||
// static when converting to member pointer.
|
Matches.push_back(std::make_pair(dap,Fn));
|
||||||
if (Method->isStatic() == IsMember)
|
}
|
||||||
continue;
|
|
||||||
} else if (IsMember)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// C++ [over.over]p2:
|
|
||||||
// If the name is a function template, template argument deduction is
|
|
||||||
// done (14.8.2.2), and if the argument deduction succeeds, the
|
|
||||||
// resulting template argument list is used to generate a single
|
|
||||||
// function template specialization, which is added to the set of
|
|
||||||
// overloaded functions considered.
|
|
||||||
FunctionDecl *Specialization = 0;
|
|
||||||
TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
|
|
||||||
if (TemplateDeductionResult Result
|
|
||||||
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
|
|
||||||
FunctionType, Specialization, Info)) {
|
|
||||||
// FIXME: make a note of the failed deduction for diagnostics.
|
|
||||||
(void)Result;
|
|
||||||
} else {
|
|
||||||
// Template argument deduction ensures that we have an exact match.
|
|
||||||
// This function template specicalization works.
|
|
||||||
Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
|
|
||||||
assert(FunctionType
|
|
||||||
== Context.getCanonicalType(Specialization->getType()));
|
|
||||||
Matches.push_back(std::make_pair(I.getPair(), Specialization));
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OvlExpr->hasExplicitTemplateArgs())
|
||||||
|
OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
|
||||||
|
|
||||||
|
if (FindAllFunctionsThatMatchTargetTypeExactly()) {
|
||||||
|
// C++ [over.over]p4:
|
||||||
|
// If more than one function is selected, [...]
|
||||||
|
if (Matches.size() > 1) {
|
||||||
|
if (FoundNonTemplateFunction)
|
||||||
|
EliminateAllTemplateMatches();
|
||||||
|
else
|
||||||
|
EliminateAllExceptMostSpecializedTemplate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isTargetTypeAFunction() const {
|
||||||
|
return TargetFunctionType->isFunctionType();
|
||||||
|
}
|
||||||
|
|
||||||
|
// [ToType] [Return]
|
||||||
|
|
||||||
|
// R (*)(A) --> R (A), IsNonStaticMemberFunction = false
|
||||||
|
// R (&)(A) --> R (A), IsNonStaticMemberFunction = false
|
||||||
|
// R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true
|
||||||
|
void inline ExtractUnqualifiedFunctionTypeFromTargetType() {
|
||||||
|
TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if any matching specializations were found
|
||||||
|
bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate,
|
||||||
|
const DeclAccessPair& CurAccessFunPair) {
|
||||||
|
if (CXXMethodDecl *Method
|
||||||
|
= dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) {
|
||||||
|
// Skip non-static function templates when converting to pointer, and
|
||||||
|
// static when converting to member pointer.
|
||||||
|
if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (TargetTypeIsNonStaticMemberFunction)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// C++ [over.over]p2:
|
||||||
|
// If the name is a function template, template argument deduction is
|
||||||
|
// done (14.8.2.2), and if the argument deduction succeeds, the
|
||||||
|
// resulting template argument list is used to generate a single
|
||||||
|
// function template specialization, which is added to the set of
|
||||||
|
// overloaded functions considered.
|
||||||
|
FunctionDecl *Specialization = 0;
|
||||||
|
TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
|
||||||
|
if (Sema::TemplateDeductionResult Result
|
||||||
|
= S.DeduceTemplateArguments(FunctionTemplate,
|
||||||
|
&OvlExplicitTemplateArgs,
|
||||||
|
TargetFunctionType, Specialization,
|
||||||
|
Info)) {
|
||||||
|
// FIXME: make a note of the failed deduction for diagnostics.
|
||||||
|
(void)Result;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template argument deduction ensures that we have an exact match.
|
||||||
|
// This function template specicalization works.
|
||||||
|
Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
|
||||||
|
assert(TargetFunctionType
|
||||||
|
== Context.getCanonicalType(Specialization->getType()));
|
||||||
|
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 (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
|
||||||
// Skip non-static functions when converting to pointer, and static
|
// Skip non-static functions when converting to pointer, and static
|
||||||
// when converting to member pointer.
|
// when converting to member pointer.
|
||||||
if (Method->isStatic() == IsMember)
|
if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
|
||||||
continue;
|
return false;
|
||||||
|
}
|
||||||
// If we have explicit template arguments, skip non-templates.
|
else if (TargetTypeIsNonStaticMemberFunction)
|
||||||
if (OvlExpr->hasExplicitTemplateArgs())
|
return false;
|
||||||
continue;
|
|
||||||
} else if (IsMember)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
|
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
|
||||||
QualType ResultTy;
|
QualType ResultTy;
|
||||||
if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
|
if (Context.hasSameUnqualifiedType(TargetFunctionType,
|
||||||
IsNoReturnConversion(Context, FunDecl->getType(), FunctionType,
|
FunDecl->getType()) ||
|
||||||
|
IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType,
|
||||||
ResultTy)) {
|
ResultTy)) {
|
||||||
Matches.push_back(std::make_pair(I.getPair(),
|
Matches.push_back(std::make_pair(CurAccessFunPair,
|
||||||
cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
|
cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
|
||||||
FoundNonTemplateFunction = true;
|
FoundNonTemplateFunction = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindAllFunctionsThatMatchTargetTypeExactly() {
|
||||||
|
bool Ret = false;
|
||||||
|
|
||||||
|
// If the overload expression doesn't have the form of a pointer to
|
||||||
|
// member, don't try to convert it to a pointer-to-member type.
|
||||||
|
if (IsInvalidFormOfPointerToMemberFunction())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
|
||||||
|
E = OvlExpr->decls_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
// Look through any using declarations to find the underlying function.
|
||||||
|
NamedDecl *Fn = (*I)->getUnderlyingDecl();
|
||||||
|
|
||||||
|
// C++ [over.over]p3:
|
||||||
|
// Non-member functions and static member functions match
|
||||||
|
// targets of type "pointer-to-function" or "reference-to-function."
|
||||||
|
// Nonstatic member functions match targets of
|
||||||
|
// type "pointer-to-member-function."
|
||||||
|
// Note that according to DR 247, the containing class does not matter.
|
||||||
|
if (FunctionTemplateDecl *FunctionTemplate
|
||||||
|
= dyn_cast<FunctionTemplateDecl>(Fn)) {
|
||||||
|
if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair()))
|
||||||
|
Ret = true;
|
||||||
|
}
|
||||||
|
// If we have explicit template arguments supplied, skip non-templates.
|
||||||
|
else if (!OvlExpr->hasExplicitTemplateArgs() &&
|
||||||
|
AddMatchingNonTemplateFunction(Fn, I.getPair()))
|
||||||
|
Ret = true;
|
||||||
|
}
|
||||||
|
assert(Ret || Matches.empty());
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there were 0 or 1 matches, we're done.
|
void EliminateAllExceptMostSpecializedTemplate() {
|
||||||
if (Matches.empty()) {
|
|
||||||
if (Complain) {
|
|
||||||
Diag(From->getLocStart(), diag::err_addr_ovl_no_viable)
|
|
||||||
<< OvlExpr->getName() << FunctionType;
|
|
||||||
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
|
|
||||||
E = OvlExpr->decls_end();
|
|
||||||
I != E; ++I)
|
|
||||||
if (FunctionDecl *F = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
|
|
||||||
NoteOverloadCandidate(F);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
} else if (Matches.size() == 1) {
|
|
||||||
FunctionDecl *Result = Matches[0].second;
|
|
||||||
FoundResult = Matches[0].first;
|
|
||||||
MarkDeclarationReferenced(From->getLocStart(), Result);
|
|
||||||
if (Complain) {
|
|
||||||
CheckAddressOfMemberAccess(OvlExpr, Matches[0].first);
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C++ [over.over]p4:
|
|
||||||
// If more than one function is selected, [...]
|
|
||||||
if (!FoundNonTemplateFunction) {
|
|
||||||
// [...] and any given function template specialization F1 is
|
// [...] and any given function template specialization F1 is
|
||||||
// eliminated if the set contains a second function template
|
// eliminated if the set contains a second function template
|
||||||
// specialization whose function template is more specialized
|
// specialization whose function template is more specialized
|
||||||
|
@ -7245,54 +7302,127 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
|
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
|
||||||
|
|
||||||
UnresolvedSetIterator Result =
|
UnresolvedSetIterator Result =
|
||||||
getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
|
S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
|
||||||
TPOC_Other, 0, From->getLocStart(),
|
TPOC_Other, 0, SourceExpr->getLocStart(),
|
||||||
PDiag(),
|
S.PDiag(),
|
||||||
PDiag(diag::err_addr_ovl_ambiguous)
|
S.PDiag(diag::err_addr_ovl_ambiguous)
|
||||||
<< Matches[0].second->getDeclName(),
|
<< Matches[0].second->getDeclName(),
|
||||||
PDiag(diag::note_ovl_candidate)
|
S.PDiag(diag::note_ovl_candidate)
|
||||||
<< (unsigned) oc_function_template);
|
<< (unsigned) oc_function_template,
|
||||||
if (Result == MatchesCopy.end())
|
Complain);
|
||||||
return 0;
|
|
||||||
|
|
||||||
MarkDeclarationReferenced(From->getLocStart(), *Result);
|
if (Result != MatchesCopy.end()) {
|
||||||
FoundResult = Matches[Result - MatchesCopy.begin()].first;
|
// Make it the first and only element
|
||||||
if (Complain)
|
Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
|
||||||
CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
|
Matches[0].second = cast<FunctionDecl>(*Result);
|
||||||
return cast<FunctionDecl>(*Result);
|
Matches.resize(1);
|
||||||
}
|
|
||||||
|
|
||||||
// [...] any function template specializations in the set are
|
|
||||||
// eliminated if the set also contains a non-template function, [...]
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [...] After such eliminations, if any, there shall remain exactly one
|
void EliminateAllTemplateMatches() {
|
||||||
// selected function.
|
// [...] any function template specializations in the set are
|
||||||
if (Matches.size() == 1) {
|
// eliminated if the set also contains a non-template function, [...]
|
||||||
MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
|
for (unsigned I = 0, N = Matches.size(); I != N; ) {
|
||||||
FoundResult = Matches[0].first;
|
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();
|
||||||
|
S.NoteAllOverloadCandidates(OvlExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsInvalidFormOfPointerToMemberFunction() const {
|
||||||
|
return TargetTypeIsNonStaticMemberFunction &&
|
||||||
|
!OvlExprInfo.HasFormOfMemberPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComplainIsInvalidFormOfPointerToMemberFunction() const {
|
||||||
|
// TODO: Should we condition this on whether any functions might
|
||||||
|
// have matched, or is it more appropriate to do that in callers?
|
||||||
|
// TODO: a fixit wouldn't hurt.
|
||||||
|
S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier)
|
||||||
|
<< TargetType << 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
|
||||||
|
/// an overloaded function (C++ [over.over]), where @p From is an
|
||||||
|
/// expression with overloaded function type and @p ToType is the type
|
||||||
|
/// we're trying to resolve to. For example:
|
||||||
|
///
|
||||||
|
/// @code
|
||||||
|
/// int f(double);
|
||||||
|
/// int f(int);
|
||||||
|
///
|
||||||
|
/// int (*pfd)(double) = f; // selects f(double)
|
||||||
|
/// @endcode
|
||||||
|
///
|
||||||
|
/// This routine returns the resulting FunctionDecl if it could be
|
||||||
|
/// resolved, and NULL otherwise. When @p Complain is true, this
|
||||||
|
/// routine will emit diagnostics if there is an error.
|
||||||
|
FunctionDecl *
|
||||||
|
Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
|
||||||
|
bool Complain,
|
||||||
|
DeclAccessPair &FoundResult) {
|
||||||
|
|
||||||
|
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();
|
||||||
|
MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn);
|
||||||
if (Complain)
|
if (Complain)
|
||||||
CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
|
CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
|
||||||
return cast<FunctionDecl>(Matches[0].second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We should probably return the same thing that BestViableFunction
|
return Fn;
|
||||||
// returns (even if we issue the diagnostics here).
|
|
||||||
if (Complain) {
|
|
||||||
Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
|
|
||||||
<< Matches[0].second->getDeclName();
|
|
||||||
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
|
|
||||||
NoteOverloadCandidate(Matches[I].second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Given an expression that refers to an overloaded function, try to
|
/// \brief Given an expression that refers to an overloaded function, try to
|
||||||
|
@ -7302,14 +7432,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
/// template, where that template-id refers to a single template whose template
|
/// template, where that template-id refers to a single template whose template
|
||||||
/// arguments are either provided by the template-id or have defaults,
|
/// arguments are either provided by the template-id or have defaults,
|
||||||
/// as described in C++0x [temp.arg.explicit]p3.
|
/// as described in C++0x [temp.arg.explicit]p3.
|
||||||
FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
|
FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
|
||||||
|
bool Complain,
|
||||||
|
DeclAccessPair* FoundResult) {
|
||||||
// C++ [over.over]p1:
|
// C++ [over.over]p1:
|
||||||
// [...] [Note: any redundant set of parentheses surrounding the
|
// [...] [Note: any redundant set of parentheses surrounding the
|
||||||
// overloaded function name is ignored (5.1). ]
|
// overloaded function name is ignored (5.1). ]
|
||||||
// C++ [over.over]p1:
|
// C++ [over.over]p1:
|
||||||
// [...] The overloaded function name can be preceded by the &
|
// [...] The overloaded function name can be preceded by the &
|
||||||
// operator.
|
// operator.
|
||||||
|
|
||||||
if (From->getType() != Context.OverloadTy)
|
if (From->getType() != Context.OverloadTy)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -7353,10 +7484,20 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple matches; we can't resolve to a single declaration.
|
// Multiple matches; we can't resolve to a single declaration.
|
||||||
if (Matched)
|
if (Matched) {
|
||||||
|
if (FoundResult)
|
||||||
|
*FoundResult = DeclAccessPair();
|
||||||
|
|
||||||
|
if (Complain) {
|
||||||
|
Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
|
||||||
|
<< OvlExpr->getName();
|
||||||
|
NoteAllOverloadCandidates(OvlExpr);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
Matched = Specialization;
|
|
||||||
|
if ((Matched = Specialization) && FoundResult)
|
||||||
|
*FoundResult = I.getPair();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Matched;
|
return Matched;
|
||||||
|
|
|
@ -1824,6 +1824,11 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
|
||||||
// template arguments that we have against the template name, if the template
|
// template arguments that we have against the template name, if the template
|
||||||
// name refers to a single template. That's not a terribly common case,
|
// name refers to a single template. That's not a terribly common case,
|
||||||
// though.
|
// though.
|
||||||
|
// foo<int> could identify a single function unambiguously
|
||||||
|
// This approach does NOT work, since f<int>(1);
|
||||||
|
// gets resolved prior to resorting to overload resolution
|
||||||
|
// i.e., template<class T> void f(double);
|
||||||
|
// vs template<class T, class U> void f(U);
|
||||||
|
|
||||||
// These should be filtered out by our callers.
|
// These should be filtered out by our callers.
|
||||||
assert(!R.empty() && "empty lookup results when building templateid");
|
assert(!R.empty() && "empty lookup results when building templateid");
|
||||||
|
|
|
@ -3322,9 +3322,11 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
const PartialDiagnostic &NoneDiag,
|
const PartialDiagnostic &NoneDiag,
|
||||||
const PartialDiagnostic &AmbigDiag,
|
const PartialDiagnostic &AmbigDiag,
|
||||||
const PartialDiagnostic &CandidateDiag) {
|
const PartialDiagnostic &CandidateDiag,
|
||||||
|
bool Complain) {
|
||||||
if (SpecBegin == SpecEnd) {
|
if (SpecBegin == SpecEnd) {
|
||||||
Diag(Loc, NoneDiag);
|
if (Complain)
|
||||||
|
Diag(Loc, NoneDiag);
|
||||||
return SpecEnd;
|
return SpecEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3370,13 +3372,15 @@ Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnose the ambiguity.
|
// Diagnose the ambiguity.
|
||||||
Diag(Loc, AmbigDiag);
|
if (Complain)
|
||||||
|
Diag(Loc, AmbigDiag);
|
||||||
|
|
||||||
|
if (Complain)
|
||||||
// FIXME: Can we order the candidates in some sane way?
|
// FIXME: Can we order the candidates in some sane way?
|
||||||
for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
|
for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
|
||||||
Diag((*I)->getLocation(), CandidateDiag)
|
Diag((*I)->getLocation(), CandidateDiag)
|
||||||
<< getTemplateArgumentBindingsText(
|
<< getTemplateArgumentBindingsText(
|
||||||
cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
|
cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
|
||||||
*cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
|
*cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
|
||||||
|
|
||||||
return SpecEnd;
|
return SpecEnd;
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
typedef __typeof__(((int*)0)-((int*)0)) ptrdiff_t;
|
||||||
|
|
||||||
|
namespace DontResolveTooEarly_WaitForOverloadResolution
|
||||||
|
{
|
||||||
|
template <class T> T* f(int); // #1
|
||||||
|
template <class T, class U> T& f(U); // #2
|
||||||
|
|
||||||
|
void g() {
|
||||||
|
int *ip = f<int>(1); // calls #1
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T* f2(int);
|
||||||
|
template <class T, class U>
|
||||||
|
T& f2(U);
|
||||||
|
|
||||||
|
void g2() {
|
||||||
|
int*ip = (f2<int>)(1); // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void twoT() { }
|
||||||
|
template<typename T, typename U>
|
||||||
|
void twoT(T) { }
|
||||||
|
|
||||||
|
|
||||||
|
void two() { }; //expected-note 5{{candidate}}
|
||||||
|
void two(int) { }; //expected-note 5{{candidate}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void one() { }
|
||||||
|
template<class T>
|
||||||
|
void oneT() { }
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void cant_resolve() { } //expected-note 3{{candidate}}
|
||||||
|
|
||||||
|
template<class T> void cant_resolve(T) { }//expected-note 3{{candidate}}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{ static_cast<void>(one); }
|
||||||
|
{ (void)(one); }
|
||||||
|
{ static_cast<void>(oneT<int>); }
|
||||||
|
{ (void)(oneT<int>); }
|
||||||
|
|
||||||
|
{ static_cast<void>(two); } // expected-error {{address of overloaded}}
|
||||||
|
{ (void)(two); } // expected-error {{address of overloaded}}
|
||||||
|
{ static_cast<void>(twoT<int>); }
|
||||||
|
{ (void)(twoT<int>); }
|
||||||
|
|
||||||
|
|
||||||
|
{ ptrdiff_t x = reinterpret_cast<ptrdiff_t>(oneT<int>); }
|
||||||
|
{ (void) reinterpret_cast<int (*)(char, double)>(oneT<int>); }
|
||||||
|
{ (void) reinterpret_cast<ptrdiff_t>(one); }
|
||||||
|
{ (void) reinterpret_cast<int (*)(char, double)>(one); }
|
||||||
|
|
||||||
|
{ ptrdiff_t x = reinterpret_cast<ptrdiff_t>(twoT<int>); }
|
||||||
|
{ (void) reinterpret_cast<int (*)(char, double)>(twoT<int>); }
|
||||||
|
{ (void) reinterpret_cast<void (*)(int)>(two); } //expected-error {{reinterpret_cast}}
|
||||||
|
{ (void) static_cast<void (*)(int)>(two); } //ok
|
||||||
|
|
||||||
|
{ (void) reinterpret_cast<int>(two); } //expected-error {{reinterpret_cast}}
|
||||||
|
{ (void) reinterpret_cast<int (*)(char, double)>(two); } //expected-error {{reinterpret_cast}}
|
||||||
|
|
||||||
|
{ bool b = (twoT<int>); } // ok
|
||||||
|
{ bool b = (twoT<int, int>); } //ok
|
||||||
|
|
||||||
|
{ bool b = &twoT<int>; //&foo<int>; }
|
||||||
|
b = &(twoT<int>); }
|
||||||
|
|
||||||
|
{ ptrdiff_t x = (ptrdiff_t) &twoT<int>;
|
||||||
|
x = (ptrdiff_t) &twoT<int>; }
|
||||||
|
|
||||||
|
{ ptrdiff_t x = (ptrdiff_t) twoT<int>;
|
||||||
|
x = (ptrdiff_t) twoT<int>; }
|
||||||
|
|
||||||
|
|
||||||
|
{ ptrdiff_t x = (ptrdiff_t) &twoT<int,int>;
|
||||||
|
x = (ptrdiff_t) &twoT<int>; }
|
||||||
|
|
||||||
|
{ oneT<int>; &oneT<int>; } //expected-warning 2{{ expression result unused }}
|
||||||
|
{ static_cast<void>(cant_resolve<int>); } // expected-error {{address of overload}}
|
||||||
|
{ bool b = cant_resolve<int>; } // expected-error {{address of overload}}
|
||||||
|
{ (void) cant_resolve<int>; } // expected-error {{address of overload}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
template<typename T> T f0(T, T);
|
template<typename T> T f0(T, T); //expected-note{{candidate}}
|
||||||
|
|
||||||
void test_f0() {
|
void test_f0() {
|
||||||
int (*f0a)(int, int) = f0;
|
int (*f0a)(int, int) = f0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||||
|
|
||||||
template<typename T> T f0(T);
|
template<typename T> T f0(T); // expected-note{{candidate function}}
|
||||||
int f0(int); // expected-note{{candidate function}}
|
int f0(int); // expected-note{{candidate function}}
|
||||||
|
|
||||||
void test_f0() {
|
void test_f0() {
|
||||||
|
@ -13,8 +13,6 @@ namespace N {
|
||||||
int f0(int); // expected-note{{candidate function}}
|
int f0(int); // expected-note{{candidate function}}
|
||||||
}
|
}
|
||||||
|
|
||||||
int f0(int);
|
|
||||||
|
|
||||||
void test_f0_2() {
|
void test_f0_2() {
|
||||||
using namespace N;
|
using namespace N;
|
||||||
int (*fp0)(int) = f0; // expected-error{{address of overloaded function 'f0' is ambiguous}}
|
int (*fp0)(int) = f0; // expected-error{{address of overloaded function 'f0' is ambiguous}}
|
||||||
|
|
|
@ -4,8 +4,8 @@ void g();
|
||||||
void f(); // expected-note 9{{candidate function}}
|
void f(); // expected-note 9{{candidate function}}
|
||||||
void f(int); // expected-note 9{{candidate function}}
|
void f(int); // expected-note 9{{candidate function}}
|
||||||
|
|
||||||
template<class T> void t(T); // expected-note 3{{candidate function}}
|
template<class T> void t(T); // expected-note 6{{candidate function}}
|
||||||
template<class T> void t(T*); // expected-note 3{{candidate function}}
|
template<class T> void t(T*); // expected-note 6{{candidate function}}
|
||||||
|
|
||||||
template<class T> void u(T);
|
template<class T> void u(T);
|
||||||
|
|
||||||
|
|
|
@ -57,11 +57,11 @@ struct B
|
||||||
|
|
||||||
struct C {
|
struct C {
|
||||||
C &getC() {
|
C &getC() {
|
||||||
return makeAC; // expected-error{{address of overloaded function 'makeAC' cannot be converted to type 'C'}}
|
return makeAC; // expected-error{{address of overloaded function 'makeAC'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
C &makeAC();
|
C &makeAC(); //expected-note{{candidate function}}
|
||||||
const C &makeAC() const;
|
const C &makeAC() const; //expected-note{{candidate function}}
|
||||||
|
|
||||||
static void f(); // expected-note{{candidate function}}
|
static void f(); // expected-note{{candidate function}}
|
||||||
static void f(int); // expected-note{{candidate function}}
|
static void f(int); // expected-note{{candidate function}}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче