[cfe-commits] r118400 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaCXXCast.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp test/CXX/expr/expr.unary/expr.unary.op/p4.cpp test/CXX/over/over.over/p2.cpp test/CXX/over/over.over/p4.cpp test/SemaCXX/addr-of-overloaded-function.cpp test/SemaCXX/static-cast.cpp
Douglas Gregor
dgregor at apple.com
Sun Nov 7 19:40:48 PST 2010
Author: dgregor
Date: Sun Nov 7 21:40:48 2010
New Revision: 118400
URL: http://llvm.org/viewvc/llvm-project?rev=118400&view=rev
Log:
Properly diagnose invalid casts to function references. Patch by
Faisal Vali, tweaked by me. Fixes PR8230.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
cfe/trunk/test/CXX/over/over.over/p2.cpp
cfe/trunk/test/CXX/over/over.over/p4.cpp
cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp
cfe/trunk/test/SemaCXX/static-cast.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Nov 7 21:40:48 2010
@@ -2449,6 +2449,12 @@
// C++ casts
// These messages adhere to the TryCast pattern: %0 is an int specifying the
// cast type, %1 is the source type, %2 is the destination type.
+def err_bad_reinterpret_cast_overload : Error<
+ "reinterpret_cast cannot resolve overloaded function %0 to type %1">;
+
+def err_bad_static_cast_overload : Error<
+ "address of overloaded function %0 cannot be static_cast to type %1">;
+
def err_bad_cxx_cast_generic : Error<
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
"functional-style cast}0 from %1 to %2 is not allowed">;
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Sun Nov 7 21:40:48 2010
@@ -21,6 +21,9 @@
#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.
@@ -37,6 +40,9 @@
CT_Functional ///< Type(expr)
};
+
+
+
static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange);
@@ -469,8 +475,21 @@
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;
+ }
+
}
@@ -495,8 +514,18 @@
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);
}
@@ -964,17 +993,20 @@
}
}
- // 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
@@ -1062,6 +1094,31 @@
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,
@@ -1071,6 +1128,12 @@
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) {
@@ -1086,6 +1149,7 @@
// This code does this transformation for the checked types.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
+
IsLValueCast = true;
}
@@ -1326,8 +1390,22 @@
}
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);
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sun Nov 7 21:40:48 2010
@@ -3202,7 +3202,12 @@
/*SuppressUserConversions*/ true,
/*AllowExplicitConversions*/ false,
/*InOverloadResolution*/ false))
- SetFailed(InitializationSequence::FK_ConversionFailed);
+ {
+ if (Initializer->getType() == Context.OverloadTy )
+ SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ else
+ SetFailed(InitializationSequence::FK_ConversionFailed);
+ }
else
setSequenceKind(StandardConversion);
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sun Nov 7 21:40:48 2010
@@ -6632,10 +6632,13 @@
// FIXME: We should probably return the same thing that BestViableFunction
// returns (even if we issue the diagnostics here).
- 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);
+ 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;
}
Modified: cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp Sun Nov 7 21:40:48 2010
@@ -7,8 +7,7 @@
template<typename T> void g(T);
void test() {
- // FIXME: this diagnostic is terrible
- foo(&g<int>); // expected-error {{cannot initialize a parameter of type 'void (test0::A::*)(int)' with an rvalue of type '<overloaded function type>'}}
+ foo(&g<int>); // expected-error {{can't form member pointer of type 'void (test0::A::*)(int)' without '&' and class name}}
}
};
}
@@ -39,7 +38,6 @@
};
void A::test() {
- // FIXME: This diagnostic is terrible.
- int (A::*ptr)(int) = &(A::foo); // expected-error {{cannot initialize a variable of type 'int (test2::A::*)(int)' with an rvalue of type '<overloaded function type>'}}
+ int (A::*ptr)(int) = &(A::foo); // expected-error {{can't form member pointer of type 'int (test2::A::*)(int)' without '&' and class name}}
}
}
Modified: cfe/trunk/test/CXX/over/over.over/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.over/p2.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p2.cpp (original)
+++ cfe/trunk/test/CXX/over/over.over/p2.cpp Sun Nov 7 21:40:48 2010
@@ -5,6 +5,5 @@
void test_f0() {
int (*f0a)(int, int) = f0;
int (*f0b)(int, int) = &f0;
- int (*f0c)(int, float) = f0; // expected-error{{cannot initialize}}
- // FIXME: poor error message above!
+ int (*f0c)(int, float) = f0; // expected-error{{address of overloaded function 'f0' does not match required type 'int (int, float)'}}
}
Modified: cfe/trunk/test/CXX/over/over.over/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.over/p4.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p4.cpp (original)
+++ cfe/trunk/test/CXX/over/over.over/p4.cpp Sun Nov 7 21:40:48 2010
@@ -17,7 +17,6 @@
void test_f0_2() {
using namespace N;
- int (*fp0)(int) = f0; // expected-error{{ambiguous}} \
- // expected-error{{cannot initialize}}
+ int (*fp0)(int) = f0; // expected-error{{address of overloaded function 'f0' is ambiguous}}
float (*fp1)(float) = f0;
}
Modified: cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp Sun Nov 7 21:40:48 2010
@@ -1,6 +1,6 @@
// 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)
@@ -9,7 +9,7 @@
// 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)
@@ -98,10 +98,10 @@
}
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}}
}
Modified: cfe/trunk/test/SemaCXX/static-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-cast.cpp?rev=118400&r1=118399&r2=118400&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-cast.cpp Sun Nov 7 21:40:48 2010
@@ -184,7 +184,7 @@
namespace PR6072 {
struct A { };
- struct B : A { void f(int); void f(); };
+ struct B : A { void f(int); void f(); }; // expected-note 2{{candidate function}}
struct C : B { };
struct D { };
@@ -192,6 +192,6 @@
(void)static_cast<void (A::*)()>(&B::f);
(void)static_cast<void (B::*)()>(&B::f);
(void)static_cast<void (C::*)()>(&B::f);
- (void)static_cast<void (D::*)()>(&B::f); // expected-error{{static_cast from '<overloaded function type>' to 'void (PR6072::D::*)()' is not allowed}}
+ (void)static_cast<void (D::*)()>(&B::f); // expected-error{{address of overloaded function 'f' cannot be static_cast to type 'void (PR6072::D::*)()'}}
}
}
More information about the cfe-commits
mailing list