#include <set>
using namespace clang;
+
+static void NoteAllOverloadCandidates(Expr* const Expr, Sema& sema);
+
enum TryCastResult {
TC_NotApplicable, ///< The cast method is not applicable.
TC_Success, ///< The cast method is appropriate and successful.
CT_Functional ///< Type(expr)
};
+
+
+
static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange);
if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
msg, Kind)
!= TC_Success && msg != 0)
- Self.Diag(OpRange.getBegin(), msg) << CT_Reinterpret
+ {
+ if (SrcExpr->getType() == Self.Context.OverloadTy)
+ {
+ //FIXME: &f<int>; is overloaded and resolvable
+ Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
+ << OverloadExpr::find(SrcExpr).Expression->getName()
+ << DestType << OpRange;
+ NoteAllOverloadCandidates(SrcExpr, Self);
+
+ }
+ else
+ Self.Diag(OpRange.getBegin(), msg) << CT_Reinterpret
<< SrcExpr->getType() << DestType << OpRange;
+ }
+
}
unsigned msg = diag::err_bad_cxx_cast_generic;
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
Kind, BasePath) != TC_Success && msg != 0)
- Self.Diag(OpRange.getBegin(), msg) << CT_Static
+ {
+ if ( SrcExpr->getType() == Self.Context.OverloadTy )
+ {
+ OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
+ Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
+ << oe->getName() << DestType << OpRange << oe->getQualifierRange();
+ NoteAllOverloadCandidates(SrcExpr, Self);
+ }
+ else
+ Self.Diag(OpRange.getBegin(), msg) << CT_Static
<< SrcExpr->getType() << DestType << OpRange;
+ }
else if (Kind == CK_Unknown || Kind == CK_BitCast)
Self.CheckCastAlign(SrcExpr, DestType, OpRange);
}
}
}
- // At this point of CheckStaticCast, if the destination is a reference,
- // this has to work. There is no other way that works.
- // On the other hand, if we're checking a C-style cast, we've still got
- // the reinterpret_cast way.
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
InitializationKind InitKind
= InitializationKind::CreateCast(/*FIXME:*/OpRange,
CStyle);
InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExpr, 1);
+
+ // At this point of CheckStaticCast, if the destination is a reference,
+ // or the expression is an overload expression this has to work.
+ // There is no other way that works.
+ // On the other hand, if we're checking a C-style cast, we've still got
+ // the reinterpret_cast way.
+
if (InitSeq.getKind() == InitializationSequence::FailedSequence &&
- (CStyle || !DestType->isReferenceType()))
+ (CStyle || !DestType->isReferenceType()))
return TC_NotApplicable;
ExprResult Result
return TC_Success;
}
+
+static void NoteAllOverloadCandidates(Expr* const Expr, Sema& sema)
+{
+
+ assert(Expr->getType() == sema.Context.OverloadTy);
+
+ OverloadExpr::FindResult Ovl = OverloadExpr::find(Expr);
+ OverloadExpr *const OvlExpr = Ovl.Expression;
+
+ for (UnresolvedSetIterator it = OvlExpr->decls_begin(),
+ end = OvlExpr->decls_end(); it != end; ++it) {
+ if ( FunctionTemplateDecl *ftd =
+ dyn_cast<FunctionTemplateDecl>((*it)->getUnderlyingDecl()) )
+ {
+ sema.NoteOverloadCandidate(ftd->getTemplatedDecl());
+ }
+ else if ( FunctionDecl *f =
+ dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl()) )
+ {
+ sema.NoteOverloadCandidate(f);
+ }
+ }
+}
+
+
static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr->getType();
+
+ // Is the source an overloaded name? (i.e. &foo)
+ // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5)
+ if (SrcType == Self.Context.OverloadTy )
+ return TC_NotApplicable;
+
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
bool LValue = DestTypeTmp->isLValueReferenceType();
if (LValue && SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) {
// This code does this transformation for the checked types.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
+
IsLValueCast = true;
}
}
if (tcr != TC_Success && msg != 0)
- Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle)
- << CastExpr->getType() << CastTy << R;
+ {
+ if (CastExpr->getType() == Context.OverloadTy)
+ {
+ DeclAccessPair Found;
+ FunctionDecl* Fn = ResolveAddressOfOverloadedFunction(CastExpr,
+ CastTy,
+ /* Complain */ true,
+ Found);
+ assert(!Fn && "cast failed but able to resolve overload expression!!");
+ }
+ else
+ {
+ Diag(R.getBegin(), msg) << (FunctionalStyle ? CT_Functional : CT_CStyle)
+ << CastExpr->getType() << CastTy << R;
+ }
+ }
else if (Kind == CK_Unknown || Kind == CK_BitCast)
CheckCastAlign(CastExpr, CastTy, R);
// RUN: %clang_cc1 -fsyntax-only -verify %s
-int f(double);
-int f(int);
+int f(double); // expected-note{{candidate function}}
+int f(int); // expected-note{{candidate function}}
int (*pfd)(double) = f; // selects f(double)
int (*pfd2)(double) = &f; // selects f(double)
// FIXME: This error message is not very good. We need to keep better
// track of what went wrong when the implicit conversion failed to
// give a better error message here.
-int (*pfe)(...) = &f; // expected-error{{cannot initialize a variable of type 'int (*)(...)' with an rvalue of type '<overloaded function type>'}}
+int (*pfe)(...) = &f; // expected-error{{address of overloaded function 'f' does not match required type 'int (...)'}}
int (&rfi)(int) = f; // selects f(int)
int (&rfd)(double) = f; // selects f(double)
}
namespace PR8033 {
- template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note{{candidate function [with T1 = const int, T2 = int]}}
- template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note{{candidate function [with T1 = int, T2 = const int]}}
+ template <typename T1, typename T2> int f(T1 *, const T2 *); // expected-note 2{{candidate function [with T1 = const int, T2 = int]}}
+ template <typename T1, typename T2> int f(const T1 *, T2 *); // expected-note 2{{candidate function [with T1 = int, T2 = const int]}}
int (*p)(const int *, const int *) = f; // expected-error{{address of overloaded function 'f' is ambiguous}} \
- // expected-error{{cannot initialize a variable of type}}
+ // expected-error{{address of overloaded function 'f' is ambiguous}}
}