[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