<div dir="ltr">I think this breaks windows bot:<div><br></div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-windows/builds/30745/steps/build%20clang%20lld/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-windows/builds/30745/steps/build%20clang%20lld/logs/stdio</a><br></div><div><br></div><div><pre style="font-family:"courier new",courier,monotype,monospace;font-size:medium"><span class="inbox-inbox-stdout">C:\PROGRA~2\MICROS~1.0\VC\bin\AMD64_~2\cl.exe   /nologo /TP -DCLANG_ENABLE_ARCMT -DCLANG_ENABLE_OBJC_REWRITER -DCLANG_ENABLE_STATIC_ANALYZER -DGTEST_HAS_RTTI=0 -DUNICODE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_GNU_SOURCE -D_HAS_EXCEPTIONS=0 -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools\clang\lib\Sema -IC:\b\slave\sanitizer-windows\llvm\tools\clang\lib\Sema -IC:\b\slave\sanitizer-windows\llvm\tools\clang\include -Itools\clang\include -Iinclude -IC:\b\slave\sanitizer-windows\llvm\include /DWIN32 /D_WINDOWS   /W4 -wd4141 -wd4146 -wd4180 -wd4244 -wd4258 -wd4267 -wd4291 -wd4345 -wd4351 -wd4355 -wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4800 -wd4100 -wd4127 -wd4512 -wd4505 -wd4610 -wd4510 -wd4702 -wd4245 -wd4706 -wd4310 -wd4701 -wd4703 -wd4389 -wd4611 -wd4805 -wd4204 -wd4577 -wd4091 -wd4592 -wd4319 -wd4324 -w14062 -we4238 /Zc:inline /Zc:strictStrings /Oi /Zc:rvalueCast /Zc:sizedDealloc- /MD /O2 /Ob2   -UNDEBUG  /EHs-c- /GR- /showIncludes /Fotools\clang\lib\Sema\CMakeFiles\clangSema.dir\SemaExprCXX.cpp.obj /Fdtools\clang\lib\Sema\CMakeFiles\clangSema.dir\ /FS -c C:\b\slave\sanitizer-windows\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp
C:\b\slave\sanitizer-windows\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp(5702): error C2326: 'clang::Sema::FindCompositePointerType::Conversion::Conversion(clang::Sema &,clang::SourceLocation,clang::Expr *&,clang::Expr *&,clang::QualType)': function cannot access 'Composite'
C:\b\slave\sanitizer-windows\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp(5702): error C2248: 'clang::InitializedEntity::InitializedEntity': cannot access private member declared in class 'clang::InitializedEntity'
C:\b\slave\sanitizer-windows\llvm\tools\clang\include\clang/Sema/Initialization.h(163): note: see declaration of 'clang::InitializedEntity::InitializedEntity'
C:\b\slave\sanitizer-windows\llvm\tools\clang\include\clang/Sema/Initialization.h(40): note: see declaration of 'clang::InitializedEntity'
C:\b\slave\sanitizer-windows\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp(5704): error C2326: 'clang::Sema::FindCompositePointerType::Conversion::Conversion(clang::Sema &,clang::SourceLocation,clang::Expr *&,clang::Expr *&,clang::QualType)': function cannot access 'Loc'
C:\b\slave\sanitizer-windows\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp(5704): error C2512: 'clang::InitializationKind::InitializationKind': no appropriate default constructor available
251843.519 [4/2/26] Building CXX object lib\Target\X86\CMakeFiles\LLVMX86CodeGen.dir\X86WinAllocaExpander.cpp.obj
251843.902 [4/1/27] Building CXX object lib\Target\X86\CMakeFiles\LLVMX86CodeGen.dir\X86TargetMachine.cpp.obj
251846.937 [4/0/28] Building CXX object lib\Target\X86\CMakeFiles\LLVMX86CodeGen.dir\X86ISelLowering.cpp.obj
ninja: build stopped: subcommand failed.
</span></pre><br class="inbox-inbox-Apple-interchange-newline"></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Oct 19, 2016 at 6:29 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br class="gmail_msg">
Date: Wed Oct 19 20:20:00 2016<br class="gmail_msg">
New Revision: 284685<br class="gmail_msg">
<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=284685&view=rev" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project?rev=284685&view=rev</a><br class="gmail_msg">
Log:<br class="gmail_msg">
Refactor and simplify Sema::FindCompositePointerType. No functionality change intended.<br class="gmail_msg">
<br class="gmail_msg">
Modified:<br class="gmail_msg">
    cfe/trunk/lib/Sema/SemaExprCXX.cpp<br class="gmail_msg">
<br class="gmail_msg">
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br class="gmail_msg">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=284685&r1=284684&r2=284685&view=diff" rel="noreferrer" class="gmail_msg" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=284685&r1=284684&r2=284685&view=diff</a><br class="gmail_msg">
==============================================================================<br class="gmail_msg">
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br class="gmail_msg">
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Oct 19 20:20:00 2016<br class="gmail_msg">
@@ -5520,7 +5520,7 @@ QualType Sema::CXXCheckConditionalOperan<br class="gmail_msg">
 /// \brief Find a merged pointer type and convert the two expressions to it.<br class="gmail_msg">
 ///<br class="gmail_msg">
 /// This finds the composite pointer type (or member pointer type) for @p E1<br class="gmail_msg">
-/// and @p E2 according to C++11 5.9p2. It converts both expressions to this<br class="gmail_msg">
+/// and @p E2 according to C++1z 5p14. It converts both expressions to this<br class="gmail_msg">
 /// type and returns it.<br class="gmail_msg">
 /// It does not emit diagnostics.<br class="gmail_msg">
 ///<br class="gmail_msg">
@@ -5538,69 +5538,87 @@ QualType Sema::FindCompositePointerType(<br class="gmail_msg">
     *NonStandardCompositeType = false;<br class="gmail_msg">
<br class="gmail_msg">
   assert(getLangOpts().CPlusPlus && "This function assumes C++");<br class="gmail_msg">
+<br class="gmail_msg">
+  // C++1z [expr]p14:<br class="gmail_msg">
+  //   The composite pointer type of two operands p1 and p2 having types T1<br class="gmail_msg">
+  //   and T2<br class="gmail_msg">
   QualType T1 = E1->getType(), T2 = E2->getType();<br class="gmail_msg">
<br class="gmail_msg">
-  // C++11 5.9p2<br class="gmail_msg">
-  //   Pointer conversions and qualification conversions are performed on<br class="gmail_msg">
-  //   pointer operands to bring them to their composite pointer type. If<br class="gmail_msg">
-  //   one operand is a null pointer constant, the composite pointer type is<br class="gmail_msg">
-  //   std::nullptr_t if the other operand is also a null pointer constant or,<br class="gmail_msg">
-  //   if the other operand is a pointer, the type of the other operand.<br class="gmail_msg">
-  if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&<br class="gmail_msg">
-      !T2->isAnyPointerType() && !T2->isMemberPointerType()) {<br class="gmail_msg">
-    if (T1->isNullPtrType() &&<br class="gmail_msg">
-        E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {<br class="gmail_msg">
-      E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();<br class="gmail_msg">
-      return T1;<br class="gmail_msg">
-    }<br class="gmail_msg">
-    if (T2->isNullPtrType() &&<br class="gmail_msg">
-        E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {<br class="gmail_msg">
-      E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();<br class="gmail_msg">
-      return T2;<br class="gmail_msg">
-    }<br class="gmail_msg">
+  //   where at least one is a pointer or pointer to member type or<br class="gmail_msg">
+  //   std::nullptr_t is:<br class="gmail_msg">
+  bool T1IsPointerLike = T1->isAnyPointerType() || T1->isMemberPointerType() ||<br class="gmail_msg">
+                         T1->isNullPtrType();<br class="gmail_msg">
+  bool T2IsPointerLike = T2->isAnyPointerType() || T2->isMemberPointerType() ||<br class="gmail_msg">
+                         T2->isNullPtrType();<br class="gmail_msg">
+  if (!T1IsPointerLike && !T2IsPointerLike)<br class="gmail_msg">
     return QualType();<br class="gmail_msg">
-  }<br class="gmail_msg">
<br class="gmail_msg">
-  if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {<br class="gmail_msg">
-    if (T2->isMemberPointerType())<br class="gmail_msg">
-      E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).get();<br class="gmail_msg">
-    else<br class="gmail_msg">
-      E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();<br class="gmail_msg">
-    return T2;<br class="gmail_msg">
-  }<br class="gmail_msg">
-  if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {<br class="gmail_msg">
-    if (T1->isMemberPointerType())<br class="gmail_msg">
-      E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).get();<br class="gmail_msg">
-    else<br class="gmail_msg">
-      E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();<br class="gmail_msg">
+  //   - if both p1 and p2 are null pointer constants, std::nullptr_t;<br class="gmail_msg">
+  // This can't actually happen, following the standard, but we also use this<br class="gmail_msg">
+  // to implement the end of [expr.conv], which hits this case.<br class="gmail_msg">
+  //<br class="gmail_msg">
+  //   - if either p1 or p2 is a null pointer constant, T2 or T1, respectively;<br class="gmail_msg">
+  if (T1IsPointerLike &&<br class="gmail_msg">
+      E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {<br class="gmail_msg">
+    E2 = ImpCastExprToType(E2, T1, T1->isMemberPointerType()<br class="gmail_msg">
+                                       ? CK_NullToMemberPointer<br class="gmail_msg">
+                                       : CK_NullToPointer).get();<br class="gmail_msg">
     return T1;<br class="gmail_msg">
   }<br class="gmail_msg">
+  if (T2IsPointerLike &&<br class="gmail_msg">
+      E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {<br class="gmail_msg">
+    E1 = ImpCastExprToType(E1, T2, T2->isMemberPointerType()<br class="gmail_msg">
+                                       ? CK_NullToMemberPointer<br class="gmail_msg">
+                                       : CK_NullToPointer).get();<br class="gmail_msg">
+    return T2;<br class="gmail_msg">
+  }<br class="gmail_msg">
<br class="gmail_msg">
   // Now both have to be pointers or member pointers.<br class="gmail_msg">
-  if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||<br class="gmail_msg">
-      (!T2->isPointerType() && !T2->isMemberPointerType()))<br class="gmail_msg">
+  if (!T1IsPointerLike || !T2IsPointerLike)<br class="gmail_msg">
     return QualType();<br class="gmail_msg">
+  assert(!T1->isNullPtrType() && !T2->isNullPtrType() &&<br class="gmail_msg">
+         "nullptr_t should be a null pointer constant");<br class="gmail_msg">
<br class="gmail_msg">
-  //   Otherwise, of one of the operands has type "pointer to cv1 void," then<br class="gmail_msg">
-  //   the other has type "pointer to cv2 T" and the composite pointer type is<br class="gmail_msg">
-  //   "pointer to cv12 void," where cv12 is the union of cv1 and cv2.<br class="gmail_msg">
-  //   Otherwise, the composite pointer type is a pointer type similar to the<br class="gmail_msg">
-  //   type of one of the operands, with a cv-qualification signature that is<br class="gmail_msg">
-  //   the union of the cv-qualification signatures of the operand types.<br class="gmail_msg">
-  // In practice, the first part here is redundant; it's subsumed by the second.<br class="gmail_msg">
-  // What we do here is, we build the two possible composite types, and try the<br class="gmail_msg">
-  // conversions in both directions. If only one works, or if the two composite<br class="gmail_msg">
-  // types are the same, we have succeeded.<br class="gmail_msg">
+  //  - if T1 or T2 is "pointer to cv1 void" and the other type is<br class="gmail_msg">
+  //    "pointer to cv2 T", "pointer to cv12 void", where cv12 is<br class="gmail_msg">
+  //    the union of cv1 and cv2;<br class="gmail_msg">
+  //  - if T1 or T2 is "pointer to noexcept function" and the other type is<br class="gmail_msg">
+  //    "pointer to function", where the function types are otherwise the same,<br class="gmail_msg">
+  //    "pointer to function";<br class="gmail_msg">
+  //     FIXME: This rule is defective: it should also permit removing noexcept<br class="gmail_msg">
+  //     from a pointer to member function.  As a Clang extension, we also<br class="gmail_msg">
+  //     permit removing 'noreturn', so we generalize this rule to;<br class="gmail_msg">
+  //     - [Clang] If T1 and T2 are both of type "pointer to function" or<br class="gmail_msg">
+  //       "pointer to member function" and the pointee types can be unified<br class="gmail_msg">
+  //       by a function pointer conversion, that conversion is applied<br class="gmail_msg">
+  //       before checking the following rules.<br class="gmail_msg">
+  //  - if T1 is "pointer to cv1 C1" and T2 is "pointer to cv2 C2", where C1<br class="gmail_msg">
+  //    is reference-related to C2 or C2 is reference-related to C1 (8.6.3),<br class="gmail_msg">
+  //    the cv-combined type of T1 and T2 or the cv-combined type of T2 and T1,<br class="gmail_msg">
+  //    respectively;<br class="gmail_msg">
+  //  - if T1 is "pointer to member of C1 of type cv1 U1" and T2 is "pointer<br class="gmail_msg">
+  //    to member of C2 of type cv2 U2" where C1 is reference-related to C2 or<br class="gmail_msg">
+  //    C2 is reference-related to C1 (8.6.3), the cv-combined type of T2 and<br class="gmail_msg">
+  //    T1 or the cv-combined type of T1 and T2, respectively;<br class="gmail_msg">
+  //  - if T1 and T2 are similar types (4.5), the cv-combined type of T1 and<br class="gmail_msg">
+  //    T2;<br class="gmail_msg">
+  //<br class="gmail_msg">
+  // If looked at in the right way, these bullets all do the same thing.<br class="gmail_msg">
+  // What we do here is, we build the two possible cv-combined types, and try<br class="gmail_msg">
+  // the conversions in both directions. If only one works, or if the two<br class="gmail_msg">
+  // composite types are the same, we have succeeded.<br class="gmail_msg">
   // FIXME: extended qualifiers?<br class="gmail_msg">
-  typedef SmallVector<unsigned, 4> QualifierVector;<br class="gmail_msg">
-  QualifierVector QualifierUnion;<br class="gmail_msg">
-  typedef SmallVector<std::pair<const Type *, const Type *>, 4><br class="gmail_msg">
-      ContainingClassVector;<br class="gmail_msg">
-  ContainingClassVector MemberOfClass;<br class="gmail_msg">
-  QualType Composite1 = Context.getCanonicalType(T1),<br class="gmail_msg">
-           Composite2 = Context.getCanonicalType(T2);<br class="gmail_msg">
+  //<br class="gmail_msg">
+  // Note that this will fail to find a composite pointer type for "pointer<br class="gmail_msg">
+  // to void" and "pointer to function". We can't actually perform the final<br class="gmail_msg">
+  // conversion in this case, even though a composite pointer type formally<br class="gmail_msg">
+  // exists.<br class="gmail_msg">
+  SmallVector<unsigned, 4> QualifierUnion;<br class="gmail_msg">
+  SmallVector<std::pair<const Type *, const Type *>, 4> MemberOfClass;<br class="gmail_msg">
+  QualType Composite1 = Context.getCanonicalType(T1);<br class="gmail_msg">
+  QualType Composite2 = Context.getCanonicalType(T2);<br class="gmail_msg">
   unsigned NeedConstBefore = 0;<br class="gmail_msg">
-  do {<br class="gmail_msg">
+  while (true) {<br class="gmail_msg">
     const PointerType *Ptr1, *Ptr2;<br class="gmail_msg">
     if ((Ptr1 = Composite1->getAs<PointerType>()) &&<br class="gmail_msg">
         (Ptr2 = Composite2->getAs<PointerType>())) {<br class="gmail_msg">
@@ -5642,7 +5660,7 @@ QualType Sema::FindCompositePointerType(<br class="gmail_msg">
<br class="gmail_msg">
     // Cannot unwrap any more types.<br class="gmail_msg">
     break;<br class="gmail_msg">
-  } while (true);<br class="gmail_msg">
+  }<br class="gmail_msg">
<br class="gmail_msg">
   if (NeedConstBefore && NonStandardCompositeType) {<br class="gmail_msg">
     // Extension: Add 'const' to qualifiers that come before the first qualifier<br class="gmail_msg">
@@ -5657,94 +5675,73 @@ QualType Sema::FindCompositePointerType(<br class="gmail_msg">
   }<br class="gmail_msg">
<br class="gmail_msg">
   // Rewrap the composites as pointers or member pointers with the union CVRs.<br class="gmail_msg">
-  ContainingClassVector::reverse_iterator MOC<br class="gmail_msg">
-    = MemberOfClass.rbegin();<br class="gmail_msg">
-  for (QualifierVector::reverse_iterator<br class="gmail_msg">
-         I = QualifierUnion.rbegin(),<br class="gmail_msg">
-         E = QualifierUnion.rend();<br class="gmail_msg">
-       I != E; (void)++I, ++MOC) {<br class="gmail_msg">
-    Qualifiers Quals = Qualifiers::fromCVRMask(*I);<br class="gmail_msg">
-    if (MOC->first && MOC->second) {<br class="gmail_msg">
+  auto MOC = MemberOfClass.rbegin();<br class="gmail_msg">
+  for (unsigned CVR : llvm::reverse(QualifierUnion)) {<br class="gmail_msg">
+    Qualifiers Quals = Qualifiers::fromCVRMask(CVR);<br class="gmail_msg">
+    auto Classes = *MOC++;<br class="gmail_msg">
+    if (Classes.first && Classes.second) {<br class="gmail_msg">
       // Rebuild member pointer type<br class="gmail_msg">
       Composite1 = Context.getMemberPointerType(<br class="gmail_msg">
-                                    Context.getQualifiedType(Composite1, Quals),<br class="gmail_msg">
-                                    MOC->first);<br class="gmail_msg">
+          Context.getQualifiedType(Composite1, Quals), Classes.first);<br class="gmail_msg">
       Composite2 = Context.getMemberPointerType(<br class="gmail_msg">
-                                    Context.getQualifiedType(Composite2, Quals),<br class="gmail_msg">
-                                    MOC->second);<br class="gmail_msg">
+          Context.getQualifiedType(Composite2, Quals), Classes.second);<br class="gmail_msg">
     } else {<br class="gmail_msg">
       // Rebuild pointer type<br class="gmail_msg">
-      Composite1<br class="gmail_msg">
-        = Context.getPointerType(Context.getQualifiedType(Composite1, Quals));<br class="gmail_msg">
-      Composite2<br class="gmail_msg">
-        = Context.getPointerType(Context.getQualifiedType(Composite2, Quals));<br class="gmail_msg">
+      Composite1 =<br class="gmail_msg">
+          Context.getPointerType(Context.getQualifiedType(Composite1, Quals));<br class="gmail_msg">
+      Composite2 =<br class="gmail_msg">
+          Context.getPointerType(Context.getQualifiedType(Composite2, Quals));<br class="gmail_msg">
     }<br class="gmail_msg">
   }<br class="gmail_msg">
<br class="gmail_msg">
-  // Try to convert to the first composite pointer type.<br class="gmail_msg">
-  InitializedEntity Entity1<br class="gmail_msg">
-    = InitializedEntity::InitializeTemporary(Composite1);<br class="gmail_msg">
-  InitializationKind Kind<br class="gmail_msg">
-    = InitializationKind::CreateCopy(Loc, SourceLocation());<br class="gmail_msg">
-  InitializationSequence E1ToC1(*this, Entity1, Kind, E1);<br class="gmail_msg">
-  InitializationSequence E2ToC1(*this, Entity1, Kind, E2);<br class="gmail_msg">
-<br class="gmail_msg">
-  if (E1ToC1 && E2ToC1) {<br class="gmail_msg">
-    // Conversion to Composite1 is viable.<br class="gmail_msg">
-    if (!Context.hasSameType(Composite1, Composite2)) {<br class="gmail_msg">
-      // Composite2 is a different type from Composite1. Check whether<br class="gmail_msg">
-      // Composite2 is also viable.<br class="gmail_msg">
-      InitializedEntity Entity2<br class="gmail_msg">
-        = InitializedEntity::InitializeTemporary(Composite2);<br class="gmail_msg">
-      InitializationSequence E1ToC2(*this, Entity2, Kind, E1);<br class="gmail_msg">
-      InitializationSequence E2ToC2(*this, Entity2, Kind, E2);<br class="gmail_msg">
-      if (E1ToC2 && E2ToC2) {<br class="gmail_msg">
-        // Both Composite1 and Composite2 are viable and are different;<br class="gmail_msg">
-        // this is an ambiguity.<br class="gmail_msg">
+  struct Conversion {<br class="gmail_msg">
+    Sema &S;<br class="gmail_msg">
+    SourceLocation Loc;<br class="gmail_msg">
+    Expr *&E1, *&E2;<br class="gmail_msg">
+    QualType Composite;<br class="gmail_msg">
+    InitializedEntity Entity =<br class="gmail_msg">
+        InitializedEntity::InitializeTemporary(Composite);<br class="gmail_msg">
+    InitializationKind Kind =<br class="gmail_msg">
+        InitializationKind::CreateCopy(Loc, SourceLocation());<br class="gmail_msg">
+    InitializationSequence E1ToC, E2ToC;<br class="gmail_msg">
+    bool Viable = E1ToC && E2ToC;<br class="gmail_msg">
+<br class="gmail_msg">
+    Conversion(Sema &S, SourceLocation Loc, Expr *&E1, Expr *&E2,<br class="gmail_msg">
+               QualType Composite)<br class="gmail_msg">
+        : S(S), Loc(Loc), E1(E1), E2(E2), Composite(Composite),<br class="gmail_msg">
+          E1ToC(S, Entity, Kind, E1), E2ToC(S, Entity, Kind, E2) {<br class="gmail_msg">
+    }<br class="gmail_msg">
+<br class="gmail_msg">
+    QualType perform() {<br class="gmail_msg">
+      ExprResult E1Result = E1ToC.Perform(S, Entity, Kind, E1);<br class="gmail_msg">
+      if (E1Result.isInvalid())<br class="gmail_msg">
         return QualType();<br class="gmail_msg">
-      }<br class="gmail_msg">
-    }<br class="gmail_msg">
+      E1 = E1Result.getAs<Expr>();<br class="gmail_msg">
<br class="gmail_msg">
-    // Convert E1 to Composite1<br class="gmail_msg">
-    ExprResult E1Result<br class="gmail_msg">
-      = E1ToC1.Perform(*this, Entity1, Kind, E1);<br class="gmail_msg">
-    if (E1Result.isInvalid())<br class="gmail_msg">
-      return QualType();<br class="gmail_msg">
-    E1 = E1Result.getAs<Expr>();<br class="gmail_msg">
-<br class="gmail_msg">
-    // Convert E2 to Composite1<br class="gmail_msg">
-    ExprResult E2Result<br class="gmail_msg">
-      = E2ToC1.Perform(*this, Entity1, Kind, E2);<br class="gmail_msg">
-    if (E2Result.isInvalid())<br class="gmail_msg">
-      return QualType();<br class="gmail_msg">
-    E2 = E2Result.getAs<Expr>();<br class="gmail_msg">
-<br class="gmail_msg">
-    return Composite1;<br class="gmail_msg">
-  }<br class="gmail_msg">
-<br class="gmail_msg">
-  // Check whether Composite2 is viable.<br class="gmail_msg">
-  InitializedEntity Entity2<br class="gmail_msg">
-    = InitializedEntity::InitializeTemporary(Composite2);<br class="gmail_msg">
-  InitializationSequence E1ToC2(*this, Entity2, Kind, E1);<br class="gmail_msg">
-  InitializationSequence E2ToC2(*this, Entity2, Kind, E2);<br class="gmail_msg">
-  if (!E1ToC2 || !E2ToC2)<br class="gmail_msg">
-    return QualType();<br class="gmail_msg">
+      ExprResult E2Result = E2ToC.Perform(S, Entity, Kind, E2);<br class="gmail_msg">
+      if (E2Result.isInvalid())<br class="gmail_msg">
+        return QualType();<br class="gmail_msg">
+      E2 = E2Result.getAs<Expr>();<br class="gmail_msg">
<br class="gmail_msg">
-  // Convert E1 to Composite2<br class="gmail_msg">
-  ExprResult E1Result<br class="gmail_msg">
-    = E1ToC2.Perform(*this, Entity2, Kind, E1);<br class="gmail_msg">
-  if (E1Result.isInvalid())<br class="gmail_msg">
-    return QualType();<br class="gmail_msg">
-  E1 = E1Result.getAs<Expr>();<br class="gmail_msg">
+      return Composite;<br class="gmail_msg">
+    }<br class="gmail_msg">
+  };<br class="gmail_msg">
<br class="gmail_msg">
-  // Convert E2 to Composite2<br class="gmail_msg">
-  ExprResult E2Result<br class="gmail_msg">
-    = E2ToC2.Perform(*this, Entity2, Kind, E2);<br class="gmail_msg">
-  if (E2Result.isInvalid())<br class="gmail_msg">
+  // Try to convert to each composite pointer type.<br class="gmail_msg">
+  Conversion C1(*this, Loc, E1, E2, Composite1);<br class="gmail_msg">
+  if (C1.Viable && Context.hasSameType(Composite1, Composite2))<br class="gmail_msg">
+    return C1.perform();<br class="gmail_msg">
+  Conversion C2(*this, Loc, E1, E2, Composite2);<br class="gmail_msg">
+<br class="gmail_msg">
+  if (C1.Viable == C2.Viable) {<br class="gmail_msg">
+    // Either Composite1 and Composite2 are viable and are different, or<br class="gmail_msg">
+    // neither is viable.<br class="gmail_msg">
+    // FIXME: How both be viable and different?<br class="gmail_msg">
     return QualType();<br class="gmail_msg">
-  E2 = E2Result.getAs<Expr>();<br class="gmail_msg">
+  }<br class="gmail_msg">
<br class="gmail_msg">
-  return Composite2;<br class="gmail_msg">
+  // Convert to the chosen type.<br class="gmail_msg">
+  return (C1.Viable ? C1 : C2).perform();<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 ExprResult Sema::MaybeBindToTemporary(Expr *E) {<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
cfe-commits mailing list<br class="gmail_msg">
<a href="mailto:cfe-commits@lists.llvm.org" class="gmail_msg" target="_blank">cfe-commits@lists.llvm.org</a><br class="gmail_msg">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" class="gmail_msg" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="gmail_msg">
</blockquote></div><div dir="ltr">-- <br></div><div data-smartmail="gmail_signature"><div dir="ltr">Mike<br>Sent from phone</div></div>