[cfe-commits] r126048 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp test/CXX/over/over.over/p2-resolve-single-template-id.cpp test/CXX/over/over.over/p2.cpp test/CXX/over/over.over/p4.cpp test/SemaCXX/addr-of-overloaded-function-casting.cpp test/SemaCXX/addr-of-overloaded-function.cpp

Douglas Gregor dgregor at apple.com
Sat Feb 19 13:32:49 PST 2011


Author: dgregor
Date: Sat Feb 19 15:32:49 2011
New Revision: 126048

URL: http://llvm.org/viewvc/llvm-project?rev=126048&view=rev
Log:
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!

Added:
    cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.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-casting.cpp
    cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Feb 19 15:32:49 2011
@@ -2686,6 +2686,10 @@
 def err_bad_static_cast_overload : Error<
   "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<
   "%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/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Feb 19 15:32:49 2011
@@ -1247,12 +1247,28 @@
                                             OverloadCandidateSet& CandidateSet,
                                             bool PartialOverloading = false);
 
+  // Emit as a 'note' the specific overload candidate
   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,
                                                    DeclAccessPair &Found);
-  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
+
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From,
+                                                   bool Complain = false,
+                                                   DeclAccessPair* Found = 0);
 
   Expr *FixOverloadedFunctionReference(Expr *E,
                                        DeclAccessPair FoundDecl,
@@ -3702,7 +3718,8 @@
                                            SourceLocation Loc,
                                            const PartialDiagnostic &NoneDiag,
                                            const PartialDiagnostic &AmbigDiag,
-                                        const PartialDiagnostic &CandidateDiag);
+                                        const PartialDiagnostic &CandidateDiag,
+                                        bool Complain = true);
 
   ClassTemplatePartialSpecializationDecl *
   getMoreSpecializedPartialSpecialization(

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Sat Feb 19 15:32:49 2011
@@ -22,7 +22,6 @@
 using namespace clang;
 
 
-static void NoteAllOverloadCandidates(Expr* const Expr, Sema& sema);
 
 enum TryCastResult {
   TC_NotApplicable, ///< The cast method is not applicable.
@@ -122,12 +121,24 @@
                                    CXXCastPath &BasePath);
 static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
                                   bool CStyle, unsigned &msg);
-static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryReinterpretCast(Sema &Self, Expr *&SrcExpr,
                                         QualType DestType, bool CStyle,
                                         const SourceRange &OpRange,
                                         unsigned &msg,
                                         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.
 ExprResult
 Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
@@ -583,7 +594,7 @@
       Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) 
         << OverloadExpr::find(SrcExpr).Expression->getName()
         << DestType << OpRange;
-      NoteAllOverloadCandidates(SrcExpr, Self);
+      Self.NoteAllOverloadCandidates(SrcExpr);
 
     } else {
       diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr, DestType);
@@ -604,7 +615,20 @@
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
   if (DestType->isVoidType()) {
     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;
   }
 
@@ -614,13 +638,12 @@
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
   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) {
       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);
+      Self.NoteAllOverloadCandidates(SrcExpr);
     } else {
       diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr, DestType);
     }
@@ -1236,32 +1259,44 @@
   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);
-    }
+// A helper function to resolve and fix an overloaded expression that
+// can be resolved because it identifies a single function
+// template specialization
+// Last three arguments should only be supplied if Complain = true
+static ExprResult ResolveAndFixSingleFunctionTemplateSpecialization(
+                    Sema &Self, Expr *SrcExpr, 
+                    bool DoFunctionPointerConverion, 
+                    bool Complain, 
+                    const SourceRange& OpRangeForComplaining, 
+                    QualType DestTypeForComplaining, 
+                    unsigned DiagIDForComplaining) {
+  assert(SrcExpr->getType() == Self.Context.OverloadTy);
+  DeclAccessPair Found;
+  bool ret = false;
+  Expr* SingleFunctionExpression = 0;
+  if (FunctionDecl* Fn = Self.ResolveSingleFunctionTemplateSpecialization(
+                                    SrcExpr, false, // false -> Complain 
+                                    &Found)) {
+    if (!Self.DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
+      // 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,
                                         const SourceRange &OpRange,
                                         unsigned &msg,
@@ -1272,9 +1307,20 @@
   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 so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ...
+  if (SrcType == Self.Context.OverloadTy) {
+    // ... 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>()) {
     bool LValue = DestTypeTmp->isLValueReferenceType();
@@ -1495,8 +1541,24 @@
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
   if (CastTy->isVoidType()) {
     IgnoredValueConversions(CastExpr);    
-    Kind = CK_ToVoid;
-    return false;
+    bool ret = false; // false is 'able to convert'
+    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
@@ -1547,7 +1609,9 @@
                                 CastTy,
                                 /* Complain */ true,
                                 Found);
-      assert(!Fn && "cast failed but able to resolve overload expression!!");
+      
+      assert(!Fn 
+                && "cast failed but able to resolve overload expression!!");
       (void)Fn;
 
     } else {

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Feb 19 15:32:49 2011
@@ -3190,7 +3190,10 @@
                               /*InOverloadResolution*/ false,
                               /*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);
     else
       SetFailed(InitializationSequence::FK_ConversionFailed);
@@ -4161,15 +4164,16 @@
       << Args[0]->getSourceRange();
     break;
 
-  case FK_ConversionFailed:
+  case FK_ConversionFailed: {
+    QualType FromType = Args[0]->getType();
     S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
       << (int)Entity.getKind()
       << DestType
       << Args[0]->isLValue()
-      << Args[0]->getType()
+      << FromType
       << Args[0]->getSourceRange();
     break;
-
+  }
   case FK_TooManyInitsForScalar: {
     SourceRange R;
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Feb 19 15:32:49 2011
@@ -1036,6 +1036,21 @@
       // We were able to resolve the address of the overloaded function,
       // so we can convert to the type of that function.
       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 (!Method->isStatic()) {
           const Type *ClassType
@@ -6349,6 +6364,27 @@
   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
 /// "lead" diagnostic; it will be given two arguments, the source and
 /// target types of the conversion.
@@ -7049,186 +7085,207 @@
   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:
-///
-/// @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 *From, QualType ToType,
-                                         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 =
-                    ToType->getAs<MemberPointerType>()) {
-    FunctionType = MemTypePtr->getPointeeType();
-    IsMember = true;
-  }
-
-  // C++ [over.over]p1:
-  //   [...] [Note: any redundant set of parentheses surrounding the
-  //   overloaded function name is ignored (5.1). ]
-  // C++ [over.over]p1:
-  //   [...] The overloaded function name can be preceded by the &
-  //   operator.
-  // However, remember whether the expression has member-pointer form:
-  // C++ [expr.unary.op]p4:
-  //     A pointer to member is only formed when an explicit & is used
-  //     and its operand is a qualified-id not enclosed in
-  //     parentheses.
-  OverloadExpr::FindResult Ovl = OverloadExpr::find(From);
-  OverloadExpr *OvlExpr = Ovl.Expression;
-
-  // We expect a pointer or reference to function, or a function pointer.
-  FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
-  if (!FunctionType->isFunctionType()) {
-    if (Complain)
-      Diag(From->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
-        << OvlExpr->getName() << ToType;
-
-    return 0;
-  }
 
-  // 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);
+// [PossiblyAFunctionType]  -->   [Return]
+// NonFunctionType --> NonFunctionType
+// R (A) --> R(A)
+// R (*)(A) --> R (A)
+// R (&)(A) --> R (A)
+// R (S::*)(A) --> R (A)
+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;
+}
 
-  // Look through all of the overloaded functions, searching for one
-  // whose type matches exactly.
+// A helper class to help with address of function resolution
+// - allows us to avoid passing around all those ugly parameters
+class AddressOfFunctionResolver 
+{
+  Sema& S;
+  Expr* SourceExpr;
+  const QualType& TargetType; 
+  QualType TargetFunctionType; // Extracted function type from target type 
+   
+  bool Complain;
+  //DeclAccessPair& ResultFunctionAccessPair;
+  ASTContext& Context;
+
+  bool TargetTypeIsNonStaticMemberFunction;
+  bool FoundNonTemplateFunction;
+
+  OverloadExpr::FindResult OvlExprInfo; 
+  OverloadExpr *OvlExpr;
+  TemplateArgumentListInfo OvlExplicitTemplateArgs;
   llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
-  llvm::SmallVector<FunctionDecl *, 4> NonMatches;
-
-  bool FoundNonTemplateFunction = 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 (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() == 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));
+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),
+      OvlExprInfo(OverloadExpr::find(SourceExpr)),
+      OvlExpr(OvlExprInfo.Expression)
+  {
+    ExtractUnqualifiedFunctionTypeFromTargetType();
+    
+    if (!TargetFunctionType->isFunctionType()) {        
+      if (OvlExpr->hasExplicitTemplateArgs()) {
+        DeclAccessPair dap;
+        if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+                                            OvlExpr, false, &dap) ) {
+          Matches.push_back(std::make_pair(dap,Fn));
+        }
       }
+      return;
+    }
+    
+    if (OvlExpr->hasExplicitTemplateArgs())
+      OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs);
 
-      continue;
+    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)) {
       // Skip non-static functions when converting to pointer, and static
       // when converting to member pointer.
-      if (Method->isStatic() == IsMember)
-        continue;
-
-      // If we have explicit template arguments, skip non-templates.
-      if (OvlExpr->hasExplicitTemplateArgs())
-        continue;
-    } else if (IsMember)
-      continue;
+      if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction)
+        return false;
+    } 
+    else if (TargetTypeIsNonStaticMemberFunction)
+      return false;
 
     if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) {
       QualType ResultTy;
-      if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
-          IsNoReturnConversion(Context, FunDecl->getType(), FunctionType,
+      if (Context.hasSameUnqualifiedType(TargetFunctionType, 
+                                         FunDecl->getType()) ||
+          IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType, 
                                ResultTy)) {
-        Matches.push_back(std::make_pair(I.getPair(),
-                           cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+        Matches.push_back(std::make_pair(CurAccessFunPair,
+          cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
         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;
 
-  // If there were 0 or 1 matches, we're done.
-  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);
+    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;
     }
-
-    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;
+    assert(Ret || Matches.empty());
+    return Ret;
   }
 
-  // C++ [over.over]p4:
-  //   If more than one function is selected, [...]
-  if (!FoundNonTemplateFunction) {
+  void EliminateAllExceptMostSpecializedTemplate() {
     //   [...] and any given function template specialization F1 is
     //   eliminated if the set contains a second function template
     //   specialization whose function template is more specialized
@@ -7245,54 +7302,127 @@
       MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
 
     UnresolvedSetIterator Result =
-        getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
-                           TPOC_Other, 0, From->getLocStart(),
-                           PDiag(),
-                           PDiag(diag::err_addr_ovl_ambiguous)
-                               << Matches[0].second->getDeclName(),
-                           PDiag(diag::note_ovl_candidate)
-                               << (unsigned) oc_function_template);
-    if (Result == MatchesCopy.end())
-      return 0;
-
-    MarkDeclarationReferenced(From->getLocStart(), *Result);
-    FoundResult = Matches[Result - MatchesCopy.begin()].first;
-    if (Complain)
-      CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
-    return cast<FunctionDecl>(*Result);
+      S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
+                           TPOC_Other, 0, 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);
+
+    if (Result != MatchesCopy.end()) {
+      // Make it the first and only element
+      Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
+      Matches[0].second = 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);
+  void EliminateAllTemplateMatches() {
+    //   [...] 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
-  // selected function.
-  if (Matches.size() == 1) {
-    MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
-    FoundResult = Matches[0].first;
-    if (Complain)
-      CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
-    return cast<FunctionDecl>(Matches[0].second);
+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;
   }
 
-  // FIXME: We should probably return the same thing that BestViableFunction
-  // 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);
+  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) {
 
-  return 0;
+  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)
+      CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
+  }
+  
+  return Fn;
 }
 
 /// \brief Given an expression that refers to an overloaded function, try to
@@ -7302,14 +7432,15 @@
 /// template, where that template-id refers to a single template whose template
 /// arguments are either provided by the template-id or have defaults,
 /// 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:
   //   [...] [Note: any redundant set of parentheses surrounding the
   //   overloaded function name is ignored (5.1). ]
   // C++ [over.over]p1:
   //   [...] The overloaded function name can be preceded by the &
   //   operator.
-
   if (From->getType() != Context.OverloadTy)
     return 0;
 
@@ -7353,10 +7484,20 @@
     }
 
     // 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;
-
-    Matched = Specialization;
+    }   
+    
+    if ((Matched = Specialization) && FoundResult) 
+      *FoundResult = I.getPair();    
   }
 
   return Matched;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Feb 19 15:32:49 2011
@@ -1824,6 +1824,11 @@
   // 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,
   // 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.
   assert(!R.empty() && "empty lookup results when building templateid");

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Sat Feb 19 15:32:49 2011
@@ -3322,9 +3322,11 @@
                          SourceLocation Loc,
                          const PartialDiagnostic &NoneDiag,
                          const PartialDiagnostic &AmbigDiag,
-                         const PartialDiagnostic &CandidateDiag) {
+                         const PartialDiagnostic &CandidateDiag,
+                         bool Complain) {
   if (SpecBegin == SpecEnd) {
-    Diag(Loc, NoneDiag);
+    if (Complain)
+      Diag(Loc, NoneDiag);
     return SpecEnd;
   }
 
@@ -3370,13 +3372,15 @@
   }
 
   // Diagnose the ambiguity.
-  Diag(Loc, AmbigDiag);
+  if (Complain)
+    Diag(Loc, AmbigDiag);
 
+  if (Complain)
   // FIXME: Can we order the candidates in some sane way?
-  for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
-    Diag((*I)->getLocation(), CandidateDiag)
-      << getTemplateArgumentBindingsText(
-        cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
+    for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I)
+      Diag((*I)->getLocation(), CandidateDiag)
+        << getTemplateArgumentBindingsText(
+          cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(),
                     *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs());
 
   return SpecEnd;

Added: cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp?rev=126048&view=auto
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp (added)
+++ cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp Sat Feb 19 15:32:49 2011
@@ -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}}
+
+}
+
+

Propchange: cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

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=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p2.cpp (original)
+++ cfe/trunk/test/CXX/over/over.over/p2.cpp Sat Feb 19 15:32:49 2011
@@ -1,6 +1,6 @@
 // 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() {
   int (*f0a)(int, int) = f0;

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=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p4.cpp (original)
+++ cfe/trunk/test/CXX/over/over.over/p4.cpp Sat Feb 19 15:32:49 2011
@@ -1,6 +1,6 @@
 // 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}}
 
 void test_f0() {
@@ -13,8 +13,6 @@
   int f0(int); // expected-note{{candidate function}}
 }
 
-int f0(int);
-
 void test_f0_2() {
   using namespace N;
   int (*fp0)(int) = f0; // expected-error{{address of overloaded function 'f0' is ambiguous}}

Modified: cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp?rev=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp (original)
+++ cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp Sat Feb 19 15:32:49 2011
@@ -4,8 +4,8 @@
 void f(); // 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 3{{candidate function}}
+template<class T> void t(T); // expected-note 6{{candidate function}}
+template<class T> void t(T*); // expected-note 6{{candidate function}}
 
 template<class T> void u(T);
 

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=126048&r1=126047&r2=126048&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp Sat Feb 19 15:32:49 2011
@@ -57,11 +57,11 @@
 
 struct C {
   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();
-  const C &makeAC() const;
+  C &makeAC();  //expected-note{{candidate function}}
+  const C &makeAC() const; //expected-note{{candidate function}}
 
   static void f(); // expected-note{{candidate function}}
   static void f(int); // expected-note{{candidate function}}





More information about the cfe-commits mailing list