<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, May 21, 2013 at 12:05 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Tue May 21 14:05:48 2013<br>
New Revision: 182406<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=182406&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=182406&view=rev</a><br>
Log:<br>
Refactor places which perform contextual implicit conversions to go through a<br>
common function. The C++1y contextual implicit conversion rules themselves are<br>
not yet implemented, however.<br>
<br>
This also fixes a subtle bug where template instantiation context notes were<br>
dropped for diagnostics coming from conversions for integral constant<br>
expressions -- we were implicitly slicing a SemaDiagnosticBuilder into a<br>
DiagnosticBuilder </blockquote><div><br></div><div style>Are there some checks (a deleted overload or a runtime check, etc) we could put in place to avoid making that mistake again/elsewhere?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
when producing these diagnostics, and losing their context<br>
notes in the process.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
    cfe/trunk/lib/Sema/SemaOverload.cpp<br>
    cfe/trunk/lib/Sema/SemaStmt.cpp<br>
    cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp<br>
    cfe/trunk/test/SemaCXX/explicit.cpp<br>
    cfe/trunk/test/SemaCXX/new-delete.cpp<br>
    cfe/trunk/test/SemaCXX/switch.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue May 21 14:05:48 2013<br>
@@ -4759,13 +4759,17 @@ def err_default_init_const : Error<<br>
 def err_delete_operand : Error<"cannot delete expression of type %0">;<br>
 def ext_delete_void_ptr_operand : ExtWarn<<br>
   "cannot delete expression with pointer-to-'void' type %0">;<br>
-def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "<br>
-                                         "expression of type %0 to a pointer">;<br>
+def err_ambiguous_delete_operand : Error<<br>
+  "ambiguous conversion of delete expression of type %0 to a pointer">;<br>
 def warn_delete_incomplete : Warning<<br>
   "deleting pointer to incomplete type %0 may cause undefined behavior">,<br>
   InGroup<DiagGroup<"delete-incomplete">>;<br>
 def err_delete_incomplete_class_type : Error<<br>
   "deleting incomplete class type %0; no conversions to pointer type">;<br>
+def err_delete_explicit_conversion : Error<<br>
+  "converting delete expression from type %0 to type %1 invokes an explicit "<br>
+  "conversion function">;<br>
+def note_delete_conversion : Note<"conversion to pointer type %0">;<br>
 def warn_delete_array_type : Warning<<br>
   "'delete' applied to a pointer-to-array type %0 treated as delete[]">;<br>
 def err_no_suitable_delete_member_function_found : Error<<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Tue May 21 14:05:48 2013<br>
@@ -906,6 +906,15 @@ public:<br>
       // Dispatch to Sema to emit the diagnostic.<br>
       SemaRef.EmitCurrentDiagnostic(DiagID);<br>
     }<br>
+<br>
+    /// Teach operator<< to produce an object of the correct type.<br>
+    template<typename T><br>
+    friend const SemaDiagnosticBuilder &operator<<(<br>
+        const SemaDiagnosticBuilder &Diag, const T &Value) {<br>
+      const DiagnosticBuilder &BaseDiag = Diag;<br>
+      BaseDiag << Value;<br>
+      return Diag;<br>
+    }<br>
   };<br>
<br>
   /// \brief Emit a diagnostic.<br>
@@ -1928,58 +1937,83 @@ public:<br>
   ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,<br>
                                               llvm::APSInt &Value, CCEKind CCE);<br>
<br>
-  /// \brief Abstract base class used to diagnose problems that occur while<br>
-  /// trying to convert an expression to integral or enumeration type.<br>
-  class ICEConvertDiagnoser {<br>
+  /// \brief Abstract base class used to perform a contextual implicit<br>
+  /// conversion from an expression to any type passing a filter.<br>
+  class ContextualImplicitConverter {<br>
   public:<br>
     bool Suppress;<br>
     bool SuppressConversion;<br>
<br>
-    ICEConvertDiagnoser(bool Suppress = false,<br>
-                        bool SuppressConversion = false)<br>
-      : Suppress(Suppress), SuppressConversion(SuppressConversion) { }<br>
+    ContextualImplicitConverter(bool Suppress = false,<br>
+                                bool SuppressConversion = false)<br>
+        : Suppress(Suppress), SuppressConversion(SuppressConversion) {}<br>
+<br>
+    /// \brief Determine whether the specified type is a valid destination type<br>
+    /// for this conversion.<br>
+    virtual bool match(QualType T) = 0;<br>
<br>
     /// \brief Emits a diagnostic complaining that the expression does not have<br>
     /// integral or enumeration type.<br>
-    virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
-                                             QualType T) = 0;<br>
+    virtual SemaDiagnosticBuilder<br>
+    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;<br>
<br>
     /// \brief Emits a diagnostic when the expression has incomplete class type.<br>
-    virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,<br>
-                                                 QualType T) = 0;<br>
+    virtual SemaDiagnosticBuilder<br>
+    diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;<br>
<br>
     /// \brief Emits a diagnostic when the only matching conversion function<br>
     /// is explicit.<br>
-    virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,<br>
-                                                   QualType T,<br>
-                                                   QualType ConvTy) = 0;<br>
+    virtual SemaDiagnosticBuilder diagnoseExplicitConv(<br>
+        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;<br>
<br>
     /// \brief Emits a note for the explicit conversion function.<br>
-    virtual DiagnosticBuilder<br>
+    virtual SemaDiagnosticBuilder<br>
     noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;<br>
<br>
     /// \brief Emits a diagnostic when there are multiple possible conversion<br>
     /// functions.<br>
-    virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
-                                                QualType T) = 0;<br>
+    virtual SemaDiagnosticBuilder<br>
+    diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;<br>
<br>
     /// \brief Emits a note for one of the candidate conversions.<br>
-    virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,<br>
-                                            QualType ConvTy) = 0;<br>
+    virtual SemaDiagnosticBuilder<br>
+    noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;<br>
<br>
     /// \brief Emits a diagnostic when we picked a conversion function<br>
     /// (for cases when we are not allowed to pick a conversion function).<br>
-    virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,<br>
-                                                 QualType T,<br>
-                                                 QualType ConvTy) = 0;<br>
+    virtual SemaDiagnosticBuilder diagnoseConversion(<br>
+        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;<br>
<br>
-    virtual ~ICEConvertDiagnoser() {}<br>
+    virtual ~ContextualImplicitConverter() {}<br>
   };<br>
<br>
-  ExprResult<br>
-  ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE,<br>
-                                     ICEConvertDiagnoser &Diagnoser,<br>
-                                     bool AllowScopedEnumerations);<br>
+  class ICEConvertDiagnoser : public ContextualImplicitConverter {<br>
+    bool AllowScopedEnumerations;<br>
+<br>
+  public:<br>
+    ICEConvertDiagnoser(bool AllowScopedEnumerations,<br>
+                        bool Suppress, bool SuppressConversion)<br>
+        : ContextualImplicitConverter(Suppress, SuppressConversion),<br>
+          AllowScopedEnumerations(AllowScopedEnumerations) {}<br>
+<br>
+    /// Match an integral or (possibly scoped) enumeration type.<br>
+    bool match(QualType T);<br>
+<br>
+    SemaDiagnosticBuilder<br>
+    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) {<br>
+      return diagnoseNotInt(S, Loc, T);<br>
+    }<br>
+<br>
+    /// \brief Emits a diagnostic complaining that the expression does not have<br>
+    /// integral or enumeration type.<br>
+    virtual SemaDiagnosticBuilder<br>
+    diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;<br>
+  };<br>
+<br>
+  /// Perform a contextual implicit conversion.<br>
+  ExprResult PerformContextualImplicitConversion(<br>
+      SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);<br>
+<br>
<br>
   enum ObjCSubscriptKind {<br>
     OS_Array,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue May 21 14:05:48 2013<br>
@@ -10391,112 +10391,52 @@ Sema::VerifyIntegerConstantExpression(Ex<br>
     //   have a single non-explicit conversion function to an integral or<br>
     //   unscoped enumeration type<br>
     ExprResult Converted;<br>
-    if (!Diagnoser.Suppress) {<br>
-      class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {<br>
-      public:<br>
-        CXX11ConvertDiagnoser() : ICEConvertDiagnoser(false, true) { }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
-                                                 QualType T) {<br>
-          return S.Diag(Loc, diag::err_ice_not_integral) << T;<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,<br>
-                                                     SourceLocation Loc,<br>
-                                                     QualType T) {<br>
-          return S.Diag(Loc, diag::err_ice_incomplete_type) << T;<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,<br>
-                                                       SourceLocation Loc,<br>
-                                                       QualType T,<br>
-                                                       QualType ConvTy) {<br>
-          return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder noteExplicitConv(Sema &S,<br>
-                                                   CXXConversionDecl *Conv,<br>
-                                                   QualType ConvTy) {<br>
-          return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)<br>
-                   << ConvTy->isEnumeralType() << ConvTy;<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
-                                                    QualType T) {<br>
-          return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder noteAmbiguous(Sema &S,<br>
-                                                CXXConversionDecl *Conv,<br>
-                                                QualType ConvTy) {<br>
-          return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)<br>
-                   << ConvTy->isEnumeralType() << ConvTy;<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseConversion(Sema &S,<br>
-                                                     SourceLocation Loc,<br>
-                                                     QualType T,<br>
-                                                     QualType ConvTy) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-      } ConvertDiagnoser;<br>
-<br>
-      Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,<br>
-                                                     ConvertDiagnoser,<br>
-                                             /*AllowScopedEnumerations*/ false);<br>
-    } else {<br>
-      // The caller wants to silently enquire whether this is an ICE. Don't<br>
-      // produce any diagnostics if it isn't.<br>
-      class SilentICEConvertDiagnoser : public ICEConvertDiagnoser {<br>
-      public:<br>
-        SilentICEConvertDiagnoser() : ICEConvertDiagnoser(true, true) { }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
-                                                 QualType T) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseIncomplete(Sema &S,<br>
-                                                     SourceLocation Loc,<br>
-                                                     QualType T) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,<br>
-                                                       SourceLocation Loc,<br>
-                                                       QualType T,<br>
-                                                       QualType ConvTy) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder noteExplicitConv(Sema &S,<br>
-                                                   CXXConversionDecl *Conv,<br>
-                                                   QualType ConvTy) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
-                                                    QualType T) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder noteAmbiguous(Sema &S,<br>
-                                                CXXConversionDecl *Conv,<br>
-                                                QualType ConvTy) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-<br>
-        virtual DiagnosticBuilder diagnoseConversion(Sema &S,<br>
-                                                     SourceLocation Loc,<br>
-                                                     QualType T,<br>
-                                                     QualType ConvTy) {<br>
-          return DiagnosticBuilder::getEmpty();<br>
-        }<br>
-      } ConvertDiagnoser;<br>
-<br>
-      Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E,<br>
-                                                     ConvertDiagnoser, false);<br>
-    }<br>
+    class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {<br>
+    public:<br>
+      CXX11ConvertDiagnoser(bool Silent)<br>
+          : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,<br>
+                                Silent, true) {}<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
+                                                   QualType T) {<br>
+        return S.Diag(Loc, diag::err_ice_not_integral) << T;<br>
+      }<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseIncomplete(<br>
+          Sema &S, SourceLocation Loc, QualType T) {<br>
+        return S.Diag(Loc, diag::err_ice_incomplete_type) << T;<br>
+      }<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseExplicitConv(<br>
+          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {<br>
+        return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;<br>
+      }<br>
+<br>
+      virtual SemaDiagnosticBuilder noteExplicitConv(<br>
+          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {<br>
+        return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)<br>
+                 << ConvTy->isEnumeralType() << ConvTy;<br>
+      }<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseAmbiguous(<br>
+          Sema &S, SourceLocation Loc, QualType T) {<br>
+        return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;<br>
+      }<br>
+<br>
+      virtual SemaDiagnosticBuilder noteAmbiguous(<br>
+          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {<br>
+        return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)<br>
+                 << ConvTy->isEnumeralType() << ConvTy;<br>
+      }<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseConversion(<br>
+          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {<br>
+        llvm_unreachable("conversion functions are permitted");<br>
+      }<br>
+    } ConvertDiagnoser(Diagnoser.Suppress);<br>
+<br>
+    Converted = PerformContextualImplicitConversion(DiagLoc, E,<br>
+                                                    ConvertDiagnoser);<br>
     if (Converted.isInvalid())<br>
       return Converted;<br>
     E = Converted.take();<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 21 14:05:48 2013<br>
@@ -1180,54 +1180,53 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
   // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped<br>
   //   enumeration type, or a class type for which a single non-explicit<br>
   //   conversion function to integral or unscoped enumeration type exists.<br>
+  // C++1y [expr.new]p6: The expression [...] is implicitly converted to<br>
+  //   std::size_t. (FIXME)<br>
   if (ArraySize && !ArraySize->isTypeDependent()) {<br>
     class SizeConvertDiagnoser : public ICEConvertDiagnoser {<br>
       Expr *ArraySize;<br>
-<br>
+<br>
     public:<br>
       SizeConvertDiagnoser(Expr *ArraySize)<br>
-        : ICEConvertDiagnoser(false, false), ArraySize(ArraySize) { }<br>
-<br>
-      virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
-                                               QualType T) {<br>
+          : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false),<br>
+            ArraySize(ArraySize) {}<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
+                                                   QualType T) {<br>
         return S.Diag(Loc, diag::err_array_size_not_integral)<br>
                  << S.getLangOpts().CPlusPlus11 << T;<br>
       }<br>
-<br>
-      virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,<br>
-                                                   QualType T) {<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseIncomplete(<br>
+          Sema &S, SourceLocation Loc, QualType T) {<br>
         return S.Diag(Loc, diag::err_array_size_incomplete_type)<br>
                  << T << ArraySize->getSourceRange();<br>
       }<br>
-<br>
-      virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S,<br>
-                                                     SourceLocation Loc,<br>
-                                                     QualType T,<br>
-                                                     QualType ConvTy) {<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseExplicitConv(<br>
+          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {<br>
         return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy;<br>
       }<br>
-<br>
-      virtual DiagnosticBuilder noteExplicitConv(Sema &S,<br>
-                                                 CXXConversionDecl *Conv,<br>
-                                                 QualType ConvTy) {<br>
+<br>
+      virtual SemaDiagnosticBuilder noteExplicitConv(<br>
+          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {<br>
         return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)<br>
                  << ConvTy->isEnumeralType() << ConvTy;<br>
       }<br>
-<br>
-      virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
-                                                  QualType T) {<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseAmbiguous(<br>
+          Sema &S, SourceLocation Loc, QualType T) {<br>
         return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T;<br>
       }<br>
-<br>
-      virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,<br>
-                                              QualType ConvTy) {<br>
+<br>
+      virtual SemaDiagnosticBuilder noteAmbiguous(<br>
+          Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {<br>
         return S.Diag(Conv->getLocation(), diag::note_array_size_conversion)<br>
                  << ConvTy->isEnumeralType() << ConvTy;<br>
       }<br>
-<br>
-      virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,<br>
-                                                   QualType T,<br>
-                                                   QualType ConvTy) {<br>
+<br>
+      virtual SemaDiagnosticBuilder diagnoseConversion(<br>
+          Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {<br>
         return S.Diag(Loc,<br>
                       S.getLangOpts().CPlusPlus11<br>
                         ? diag::warn_cxx98_compat_array_size_conversion<br>
@@ -1237,8 +1236,7 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
     } SizeDiagnoser(ArraySize);<br>
<br>
     ExprResult ConvertedSize<br>
-      = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, SizeDiagnoser,<br>
-                                           /*AllowScopedEnumerations*/ false);<br>
+      = PerformContextualImplicitConversion(StartLoc, ArraySize, SizeDiagnoser);<br>
     if (ConvertedSize.isInvalid())<br>
       return ExprError();<br>
<br>
@@ -2054,7 +2052,8 @@ Sema::ActOnCXXDelete(SourceLocation Star<br>
                      bool ArrayForm, Expr *ExE) {<br>
   // C++ [expr.delete]p1:<br>
   //   The operand shall have a pointer type, or a class type having a single<br>
-  //   conversion function to a pointer type. The result has type void.<br>
+  //   non-explicit conversion function to a pointer type. The result has type<br>
+  //   void.<br>
   //<br>
   // DR599 amends "pointer type" to "pointer to object type" in both cases.<br>
<br>
@@ -2071,59 +2070,65 @@ Sema::ActOnCXXDelete(SourceLocation Star<br>
<br>
     QualType Type = Ex.get()->getType();<br>
<br>
-    if (const RecordType *Record = Type->getAs<RecordType>()) {<br>
-      if (RequireCompleteType(StartLoc, Type,<br>
-                              diag::err_delete_incomplete_class_type))<br>
-        return ExprError();<br>
+    class DeleteConverter : public ContextualImplicitConverter {<br>
+    public:<br>
+      DeleteConverter() : ContextualImplicitConverter(false, true) {}<br>
<br>
-      SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions;<br>
+      bool match(QualType ConvType) {<br>
+        // FIXME: If we have an operator T* and an operator void*, we must pick<br>
+        // the operator T*.<br>
+        if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())<br>
+          if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())<br>
+            return true;<br>
+        return false;<br>
+      }<br>
<br>
-      CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());<br>
-      std::pair<CXXRecordDecl::conversion_iterator,<br>
-                CXXRecordDecl::conversion_iterator><br>
-        Conversions = RD->getVisibleConversionFunctions();<br>
-      for (CXXRecordDecl::conversion_iterator<br>
-             I = Conversions.first, E = Conversions.second; I != E; ++I) {<br>
-        NamedDecl *D = I.getDecl();<br>
-        if (isa<UsingShadowDecl>(D))<br>
-          D = cast<UsingShadowDecl>(D)->getTargetDecl();<br>
+      SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,<br>
+                                            QualType T) {<br>
+        return S.Diag(Loc, diag::err_delete_operand) << T;<br>
+      }<br>
<br>
-        // Skip over templated conversion functions; they aren't considered.<br>
-        if (isa<FunctionTemplateDecl>(D))<br>
-          continue;<br>
+      SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,<br>
+                                               QualType T) {<br>
+        return S.Diag(Loc, diag::err_delete_incomplete_class_type) << T;<br>
+      }<br>
<br>
-        CXXConversionDecl *Conv = cast<CXXConversionDecl>(D);<br>
+      SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,<br>
+                                                 QualType T, QualType ConvTy) {<br>
+        return S.Diag(Loc, diag::err_delete_explicit_conversion) << T << ConvTy;<br>
+      }<br>
<br>
-        QualType ConvType = Conv->getConversionType().getNonReferenceType();<br>
-        if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())<br>
-          if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType())<br>
-            ObjectPtrConversions.push_back(Conv);<br>
+      SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,<br>
+                                             QualType ConvTy) {<br>
+        return S.Diag(Conv->getLocation(), diag::note_delete_conversion)<br>
+          << ConvTy;<br>
       }<br>
-      if (ObjectPtrConversions.size() == 1) {<br>
-        // We have a single conversion to a pointer-to-object type. Perform<br>
-        // that conversion.<br>
-        // TODO: don't redo the conversion calculation.<br>
-        ExprResult Res =<br>
-          PerformImplicitConversion(Ex.get(),<br>
-                            ObjectPtrConversions.front()->getConversionType(),<br>
-                                    AA_Converting);<br>
-        if (Res.isUsable()) {<br>
-          Ex = Res;<br>
-          Type = Ex.get()->getType();<br>
-        }<br>
+<br>
+      SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
+                                              QualType T) {<br>
+        return S.Diag(Loc, diag::err_ambiguous_delete_operand) << T;<br>
       }<br>
-      else if (ObjectPtrConversions.size() > 1) {<br>
-        Diag(StartLoc, diag::err_ambiguous_delete_operand)<br>
-              << Type << Ex.get()->getSourceRange();<br>
-        for (unsigned i= 0; i < ObjectPtrConversions.size(); i++)<br>
-          NoteOverloadCandidate(ObjectPtrConversions[i]);<br>
-        return ExprError();<br>
+<br>
+      SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,<br>
+                                          QualType ConvTy) {<br>
+        return S.Diag(Conv->getLocation(), diag::note_delete_conversion)<br>
+          << ConvTy;<br>
       }<br>
-    }<br>
<br>
-    if (!Type->isPointerType())<br>
-      return ExprError(Diag(StartLoc, diag::err_delete_operand)<br>
-        << Type << Ex.get()->getSourceRange());<br>
+      SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,<br>
+                                               QualType T, QualType ConvTy) {<br>
+        llvm_unreachable("conversion functions are permitted");<br>
+      }<br>
+    } Converter;<br>
+<br>
+    Ex = PerformContextualImplicitConversion(StartLoc, Ex.take(), Converter);<br>
+    if (Ex.isInvalid())<br>
+      return ExprError();<br>
+    Type = Ex.get()->getType();<br>
+    if (!Converter.match(Type))<br>
+      // FIXME: PerformContextualImplicitConversion should return ExprError<br>
+      //        itself in this case.<br>
+      return ExprError();<br>
<br>
     QualType Pointee = Type->getAs<PointerType>()->getPointeeType();<br>
     QualType PointeeElem = Context.getBaseElementType(Pointee);<br>
@@ -2246,7 +2251,6 @@ Sema::ActOnCXXDelete(SourceLocation Star<br>
                       PDiag(diag::err_access_dtor) << PointeeElem);<br>
       }<br>
     }<br>
-<br>
   }<br>
<br>
   return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue May 21 14:05:48 2013<br>
@@ -5116,34 +5116,31 @@ ExprResult Sema::PerformContextuallyConv<br>
<br>
 /// Determine whether the provided type is an integral type, or an enumeration<br>
 /// type of a permitted flavor.<br>
-static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) {<br>
-  return AllowScopedEnum ? T->isIntegralOrEnumerationType()<br>
-                         : T->isIntegralOrUnscopedEnumerationType();<br>
+bool Sema::ICEConvertDiagnoser::match(QualType T) {<br>
+  return AllowScopedEnumerations ? T->isIntegralOrEnumerationType()<br>
+                                 : T->isIntegralOrUnscopedEnumerationType();<br>
 }<br>
<br>
-/// \brief Attempt to convert the given expression to an integral or<br>
-/// enumeration type.<br>
+/// \brief Attempt to convert the given expression to a type which is accepted<br>
+/// by the given converter.<br>
 ///<br>
-/// This routine will attempt to convert an expression of class type to an<br>
-/// integral or enumeration type, if that class type only has a single<br>
-/// conversion to an integral or enumeration type.<br>
+/// This routine will attempt to convert an expression of class type to a<br>
+/// type accepted by the specified converter. In C++11 and before, the class<br>
+/// must have a single non-explicit conversion function converting to a matching<br>
+/// type. In C++1y, there can be multiple such conversion functions, but only<br>
+/// one target type.<br>
 ///<br>
 /// \param Loc The source location of the construct that requires the<br>
 /// conversion.<br>
 ///<br>
 /// \param From The expression we're converting from.<br>
 ///<br>
-/// \param Diagnoser Used to output any diagnostics.<br>
-///<br>
-/// \param AllowScopedEnumerations Specifies whether conversions to scoped<br>
-/// enumerations should be considered.<br>
+/// \param Converter Used to control and diagnose the conversion process.<br>
 ///<br>
 /// \returns The expression, converted to an integral or enumeration type if<br>
 /// successful.<br>
-ExprResult<br>
-Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From,<br>
-                                         ICEConvertDiagnoser &Diagnoser,<br>
-                                         bool AllowScopedEnumerations) {<br>
+ExprResult Sema::PerformContextualImplicitConversion(<br>
+    SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) {<br>
   // We can't perform any more checking for type-dependent expressions.<br>
   if (From->isTypeDependent())<br>
     return Owned(From);<br>
@@ -5155,34 +5152,34 @@ Sema::ConvertToIntegralOrEnumerationType<br>
     From = result.take();<br>
   }<br>
<br>
-  // If the expression already has integral or enumeration type, we're golden.<br>
+  // If the expression already has a matching type, we're golden.<br>
   QualType T = From->getType();<br>
-  if (isIntegralOrEnumerationType(T, AllowScopedEnumerations))<br>
+  if (Converter.match(T))<br>
     return DefaultLvalueConversion(From);<br>
<br>
   // FIXME: Check for missing '()' if T is a function type?<br>
<br>
-  // If we don't have a class type in C++, there's no way we can get an<br>
-  // expression of integral or enumeration type.<br>
+  // We can only perform contextual implicit conversions on objects of class<br>
+  // type.<br>
   const RecordType *RecordTy = T->getAs<RecordType>();<br>
   if (!RecordTy || !getLangOpts().CPlusPlus) {<br>
-    if (!Diagnoser.Suppress)<br>
-      Diagnoser.diagnoseNotInt(*this, Loc, T) << From->getSourceRange();<br>
+    if (!Converter.Suppress)<br>
+      Converter.diagnoseNoMatch(*this, Loc, T) << From->getSourceRange();<br>
     return Owned(From);<br>
   }<br>
<br>
   // We must have a complete class type.<br>
   struct TypeDiagnoserPartialDiag : TypeDiagnoser {<br>
-    ICEConvertDiagnoser &Diagnoser;<br>
+    ContextualImplicitConverter &Converter;<br>
     Expr *From;<br>
-<br>
-    TypeDiagnoserPartialDiag(ICEConvertDiagnoser &Diagnoser, Expr *From)<br>
-      : TypeDiagnoser(Diagnoser.Suppress), Diagnoser(Diagnoser), From(From) {}<br>
-<br>
+<br>
+    TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)<br>
+        : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}<br>
+<br>
     virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {<br>
-      Diagnoser.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();<br>
+      Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();<br>
     }<br>
-  } IncompleteDiagnoser(Diagnoser, From);<br>
+  } IncompleteDiagnoser(Converter, From);<br>
<br>
   if (RequireCompleteType(Loc, T, IncompleteDiagnoser))<br>
     return Owned(From);<br>
@@ -5201,9 +5198,8 @@ Sema::ConvertToIntegralOrEnumerationType<br>
          I = Conversions.first, E = Conversions.second; I != E; ++I) {<br>
     if (CXXConversionDecl *Conversion<br>
           = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {<br>
-      if (isIntegralOrEnumerationType(<br>
-            Conversion->getConversionType().getNonReferenceType(),<br>
-            AllowScopedEnumerations)) {<br>
+      if (Converter.match(<br>
+              Conversion->getConversionType().getNonReferenceType())) {<br>
         if (Conversion->isExplicit())<br>
           ExplicitConversions.addDecl(I.getDecl(), I.getAccess());<br>
         else<br>
@@ -5212,9 +5208,10 @@ Sema::ConvertToIntegralOrEnumerationType<br>
     }<br>
   }<br>
<br>
+  // FIXME: Implement the C++11 rules!<br>
   switch (ViableConversions.size()) {<br>
   case 0:<br>
-    if (ExplicitConversions.size() == 1 && !Diagnoser.Suppress) {<br>
+    if (ExplicitConversions.size() == 1 && !Converter.Suppress) {<br>
       DeclAccessPair Found = ExplicitConversions[0];<br>
       CXXConversionDecl *Conversion<br>
         = cast<CXXConversionDecl>(Found->getUnderlyingDecl());<br>
@@ -5226,12 +5223,12 @@ Sema::ConvertToIntegralOrEnumerationType<br>
       std::string TypeStr;<br>
       ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy());<br>
<br>
-      Diagnoser.diagnoseExplicitConv(*this, Loc, T, ConvTy)<br>
+      Converter.diagnoseExplicitConv(*this, Loc, T, ConvTy)<br>
         << FixItHint::CreateInsertion(From->getLocStart(),<br>
                                       "static_cast<" + TypeStr + ">(")<br>
         << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),<br>
                                       ")");<br>
-      Diagnoser.noteExplicitConv(*this, Conversion, ConvTy);<br>
+      Converter.noteExplicitConv(*this, Conversion, ConvTy);<br>
<br>
       // If we aren't in a SFINAE context, build a call to the<br>
       // explicit conversion function.<br>
@@ -5262,11 +5259,11 @@ Sema::ConvertToIntegralOrEnumerationType<br>
       = cast<CXXConversionDecl>(Found->getUnderlyingDecl());<br>
     QualType ConvTy<br>
       = Conversion->getConversionType().getNonReferenceType();<br>
-    if (!Diagnoser.SuppressConversion) {<br>
+    if (!Converter.SuppressConversion) {<br>
       if (isSFINAEContext())<br>
         return ExprError();<br>
<br>
-      Diagnoser.diagnoseConversion(*this, Loc, T, ConvTy)<br>
+      Converter.diagnoseConversion(*this, Loc, T, ConvTy)<br>
         << From->getSourceRange();<br>
     }<br>
<br>
@@ -5283,24 +5280,22 @@ Sema::ConvertToIntegralOrEnumerationType<br>
   }<br>
<br>
   default:<br>
-    if (Diagnoser.Suppress)<br>
+    if (Converter.Suppress)<br>
       return ExprError();<br>
<br>
-    Diagnoser.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange();<br>
+    Converter.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange();<br>
     for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {<br>
       CXXConversionDecl *Conv<br>
         = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());<br>
       QualType ConvTy = Conv->getConversionType().getNonReferenceType();<br>
-      Diagnoser.noteAmbiguous(*this, Conv, ConvTy);<br>
+      Converter.noteAmbiguous(*this, Conv, ConvTy);<br>
     }<br>
     return Owned(From);<br>
   }<br>
<br>
-  if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) &&<br>
-      !Diagnoser.Suppress) {<br>
-    Diagnoser.diagnoseNotInt(*this, Loc, From->getType())<br>
+  if (!Converter.match(From->getType()) && !Converter.Suppress)<br>
+    Converter.diagnoseNoMatch(*this, Loc, From->getType())<br>
       << From->getSourceRange();<br>
-  }<br>
<br>
   return DefaultLvalueConversion(From);<br>
 }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue May 21 14:05:48 2013<br>
@@ -592,52 +592,50 @@ Sema::ActOnStartOfSwitchStmt(SourceLocat<br>
<br>
   public:<br>
     SwitchConvertDiagnoser(Expr *Cond)<br>
-      : ICEConvertDiagnoser(false, true), Cond(Cond) { }<br>
+        : ICEConvertDiagnoser(/*AllowScopedEnumerations*/true, false, true),<br>
+          Cond(Cond) {}<br>
<br>
-    virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
-                                             QualType T) {<br>
+    virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,<br>
+                                                 QualType T) {<br>
       return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T;<br>
     }<br>
<br>
-    virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,<br>
-                                                 QualType T) {<br>
+    virtual SemaDiagnosticBuilder diagnoseIncomplete(<br>
+        Sema &S, SourceLocation Loc, QualType T) {<br>
       return S.Diag(Loc, diag::err_switch_incomplete_class_type)<br>
                << T << Cond->getSourceRange();<br>
     }<br>
<br>
-    virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,<br>
-                                                   QualType T,<br>
-                                                   QualType ConvTy) {<br>
+    virtual SemaDiagnosticBuilder diagnoseExplicitConv(<br>
+        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {<br>
       return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy;<br>
     }<br>
<br>
-    virtual DiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,<br>
-                                               QualType ConvTy) {<br>
+    virtual SemaDiagnosticBuilder noteExplicitConv(<br>
+        Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {<br>
       return S.Diag(Conv->getLocation(), diag::note_switch_conversion)<br>
         << ConvTy->isEnumeralType() << ConvTy;<br>
     }<br>
<br>
-    virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
-                                                QualType T) {<br>
+    virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,<br>
+                                                    QualType T) {<br>
       return S.Diag(Loc, diag::err_switch_multiple_conversions) << T;<br>
     }<br>
<br>
-    virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,<br>
-                                            QualType ConvTy) {<br>
+    virtual SemaDiagnosticBuilder noteAmbiguous(<br>
+        Sema &S, CXXConversionDecl *Conv, QualType ConvTy) {<br>
       return S.Diag(Conv->getLocation(), diag::note_switch_conversion)<br>
       << ConvTy->isEnumeralType() << ConvTy;<br>
     }<br>
<br>
-    virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc,<br>
-                                                 QualType T,<br>
-                                                 QualType ConvTy) {<br>
-      return DiagnosticBuilder::getEmpty();<br>
+    virtual SemaDiagnosticBuilder diagnoseConversion(<br>
+        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) {<br>
+      llvm_unreachable("conversion functions are permitted");<br>
     }<br>
   } SwitchDiagnoser(Cond);<br>
<br>
-  CondResult<br>
-    = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, SwitchDiagnoser,<br>
-                                         /*AllowScopedEnumerations*/ true);<br>
+  CondResult =<br>
+      PerformContextualImplicitConversion(SwitchLoc, Cond, SwitchDiagnoser);<br>
   if (CondResult.isInvalid()) return StmtError();<br>
   Cond = CondResult.take();<br>
<br>
<br>
Modified: cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/conversion-delete-expr.cpp Tue May 21 14:05:48 2013<br>
@@ -2,11 +2,11 @@<br>
<br>
 // Test1<br>
 struct B {<br>
-  operator char *(); // expected-note {{candidate function}}<br>
+  operator char *(); // expected-note {{conversion to pointer type}}<br>
 };<br>
<br>
 struct D : B {<br>
-  operator int *(); // expected-note {{candidate function}}<br>
+  operator int *(); // expected-note {{conversion to pointer type}}<br>
 };<br>
<br>
 void f (D d)<br>
@@ -30,11 +30,11 @@ void f1 (D1 d)<br>
<br>
 // Test3<br>
 struct B2 {<br>
-  operator const int *();      // expected-note {{candidate function}}<br>
+  operator const int *(); // expected-note {{conversion to pointer type}}<br>
 };<br>
<br>
 struct D2 : B2 {<br>
-  operator int *();    // expected-note {{candidate function}}<br>
+  operator int *(); // expected-note {{conversion to pointer type}}<br>
 };<br>
<br>
 void f2 (D2 d)<br>
@@ -44,11 +44,11 @@ void f2 (D2 d)<br>
<br>
 // Test4<br>
 struct B3 {<br>
-  operator const int *();      // expected-note {{candidate function}}<br>
+  operator const int *(); // expected-note {{conversion to pointer type}}<br>
 };<br>
<br>
 struct A3 {<br>
-  operator const int *();      // expected-note {{candidate function}}<br>
+  operator const int *(); // expected-note {{conversion to pointer type}}<br>
 };<br>
<br>
 struct D3 : A3, B3 {<br>
@@ -78,7 +78,7 @@ void f5(X1 x) { delete x; }  // OK. In s<br>
<br>
 // Test7<br>
 struct Base {<br>
-   operator int*();<br>
+   operator int*();<br>
 };<br>
<br>
 struct Derived : Base {<br>
@@ -87,9 +87,9 @@ struct Derived : Base {<br>
 };<br>
<br>
 void foo6(const Derived cd, Derived d) {<br>
-       // overload resolution selects Derived::operator int*() const;<br>
-       delete cd;<br>
-       delete d;<br>
+  // overload resolution selects Derived::operator int*() const;<br>
+  delete cd;<br>
+  delete d;<br>
 }<br>
<br>
 // Test8<br>
@@ -104,6 +104,6 @@ struct DD : BB {<br>
<br>
 void foo7 (DD d)<br>
 {<br>
-        // OK. In selecting a conversion to pointer function, template convesions are skipped.<br>
-       delete d;<br>
+  // OK. In selecting a conversion to pointer function, template convesions are skipped.<br>
+  delete d;<br>
 }<br>
<br>
Modified: cfe/trunk/test/SemaCXX/explicit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/explicit.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/explicit.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/explicit.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/explicit.cpp Tue May 21 14:05:48 2013<br>
@@ -145,14 +145,14 @@ namespace Conversion {<br>
       operator int*();<br>
     };<br>
     struct NotPtr {<br>
-      explicit operator int*();<br>
+      explicit operator int*(); // expected-note {{conversion}}<br>
     };<br>
<br>
     Ptr    p;<br>
     NotPtr np;<br>
<br>
     delete p;<br>
-    delete np; // expected-error {{cannot delete expression of type 'NotPtr'}}<br>
+    delete np; // expected-error {{converting delete expression from type 'NotPtr' to type 'int *' invokes an explicit conversion function}}<br>
   }<br>
<br>
   void testFunctionPointer()<br>
<br>
Modified: cfe/trunk/test/SemaCXX/new-delete.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Tue May 21 14:05:48 2013<br>
@@ -116,8 +116,8 @@ struct X1 {<br>
 };<br>
<br>
 struct X2 {<br>
-  operator int*(); // expected-note {{candidate function}}<br>
-  operator float*(); // expected-note {{candidate function}}<br>
+  operator int*(); // expected-note {{conversion}}<br>
+  operator float*(); // expected-note {{conversion}}<br>
 };<br>
<br>
 void test_delete_conv(X0 x0, X1 x1, X2 x2) {<br>
<br>
Modified: cfe/trunk/test/SemaCXX/switch.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch.cpp?rev=182406&r1=182405&r2=182406&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/switch.cpp?rev=182406&r1=182405&r2=182406&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/switch.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/switch.cpp Tue May 21 14:05:48 2013<br>
@@ -85,3 +85,18 @@ void local_class(int n) {<br>
     }();<br>
   }<br>
 }<br>
+<br>
+namespace Conversion {<br>
+  struct S {<br>
+    explicit operator int(); // expected-note {{conversion}}<br>
+  };<br>
+  template<typename T> void f(T t) {<br>
+    switch (t) { // expected-error {{explicit conversion}}<br>
+    case 0:<br>
+      return;<br>
+    default:<br>
+      break;<br>
+    }<br>
+  }<br>
+  template void f(S); // expected-note {{instantiation of}}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>