On Tue, May 21, 2013 at 2:01 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote"><div class="im">On Tue, May 21, 2013 at 12:47 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@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"><div>On Tue, May 21, 2013 at 12:38 PM, David Blaikie <span dir="ltr"><<a href="mailto:dblaikie@gmail.com" target="_blank">dblaikie@gmail.com</a>></span> wrote:<br>

</div><div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr">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><div class="gmail_extra">

<div class="gmail_quote">
<div>
<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><div>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></div></blockquote>


<div><br></div></div><div>A runtime check is definitely possible -- we can store a flag in SemaDiagnosticBuilder to indicate that it owns some context notes, copy and clear the flag when its ownership is transferred to another SemaDiagnosticBuilder, and assert in the destructor if the flag is set but the object is not active. But a compile-time check would be better.</div>


<div><br></div><div>A deleted conversion function to the base class seems exactly what we want here, except that such a conversion function wouldn't actually ever be used...</div></div></blockquote><div><br></div></div>
<div>
I couldn't quite find the particular case that was the original problem in your patch, so I'm not sure what you mean by "such a conversion function wouldn't ever be used" - I guess you mean that the code went through something like:<br>

<br>SDB x...<br>DB &y = x;<br>DB z(y);<br><br>& thus the ctor call wouldn't've failed in the presence of DB(SDB&) = delete.</div></div></div></div></blockquote><div><br></div><div>I was talking about a conversion function, not a converting constructor. "SDB::operator DB() = delete" would never be called, because DB is a base class. We shouldn't add "DB(SDB&) = delete" because that would be a layering violation.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div class="im"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="gmail_quote"><div> and we don't want the base class to know about SemaDiagnosticBuilder so we can't put a deleted constructor there.</div></div></blockquote><div><br></div></div><div>Fair enough (could do it as a conversion operator from SemadiagnosticBuilder to DiagnosticBuilder, perhaps)</div>
</div></div></div></blockquote><div><br></div><div>:) See above.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra">
<div class="gmail_quote"><div> </div><div class="im"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div> Now that we've provided a forwarding operator<< for SemaDiagnosticBuilder, we could possibly switch from using DiagnosticBuilder as a (public) base class to either a private base or a data member.</div>

</div></blockquote><div><br></div></div><div>If this is possible, I don't see why the = delete option wouldn't be, but in any case I'm OK with that (encapsulation is nicer anyway - leaks less than inheritance).<br>

<br>I tried a quick go at this & hit a couple of issues:<br>1) op bool from DiagnosticBuilder required in SemaDiagnosticBuilder - trivial to add<br>2) some other pieces of infrastructure, like ActionResult, are used frequently & produce implicit conversions from SemaDiagnosticBuilder& to DiagnosticBuilder& - I haven't tried to fix/workaround that as yet</div>
</div></div></div></blockquote><div><br></div><div>We could add an operator ActionResult<T> to SDB, perhaps.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </div><div><div class="h5"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote">
<div><div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> </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" target="_blank">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></div></div><br></div></div>
</blockquote></div></div></div><br>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br>