Re: r284685 - Refactor and simplify Sema::FindCompositePointerType. No functionality change intended.

2016-10-20 Thread Richard Smith via cfe-commits
Should hopefully be fixed by r284701.

On Thu, Oct 20, 2016 at 12:55 AM, Richard Smith 
wrote:

> I think I understand the MSVC bug here; workaround incoming.
>
> On Wed, Oct 19, 2016 at 11:54 PM, Mike Aizatsky 
> wrote:
>
>> I think this breaks windows bot:
>>
>> http://lab.llvm.org:8011/builders/sanitizer-windows/builds/
>> 30745/steps/build%20clang%20lld/logs/stdio
>>
>> 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.
>>
>>
>>
>> On Wed, Oct 19, 2016 at 6:29 PM Richard Smith via cfe-commits <
>> cfe-commits@lists.llvm.org> wrote:
>>
>>> Author: rsmith
>>> Date: Wed Oct 19 20:20:00 2016
>>> New Revision: 284685
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=284685=rev
>>> Log:
>>> Refactor and simplify Sema::FindCompositePointerType. No functionality
>>> change intended.
>>>
>>> Modified:
>>> cfe/trunk/lib/Sema/SemaExprCXX.cpp
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaE
>>> xprCXX.cpp?rev=284685=284684=284685=diff
>>> 
>>> ==
>>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Oct 19 20:20:00 2016
>>> @@ -5520,7 +5520,7 @@ QualType Sema::CXXCheckConditionalOperan
>>>  /// \brief Find a merged pointer type and convert the two expressions
>>> to it.
>>>  ///
>>>  /// This finds the composite pointer type (or member pointer type) for
>>> @p E1
>>> -/// and @p E2 according to C++11 5.9p2. It converts both expressions to
>>> this
>>> +/// and @p E2 according to C++1z 5p14. It converts both expressions to
>>> this
>>>  /// type and returns it.
>>>  /// It does not emit diagnostics.
>>>  ///
>>> @@ -5538,69 +5538,87 @@ QualType Sema::FindCompositePointerType(
>>>  *NonStandardCompositeType = false;
>>>
>>>assert(getLangOpts().CPlusPlus && 

Re: r284685 - Refactor and simplify Sema::FindCompositePointerType. No functionality change intended.

2016-10-20 Thread Richard Smith via cfe-commits
I think I understand the MSVC bug here; workaround incoming.

On Wed, Oct 19, 2016 at 11:54 PM, Mike Aizatsky  wrote:

> I think this breaks windows bot:
>
> http://lab.llvm.org:8011/builders/sanitizer-windows/
> builds/30745/steps/build%20clang%20lld/logs/stdio
>
> 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.
>
>
>
> On Wed, Oct 19, 2016 at 6:29 PM Richard Smith via cfe-commits <
> cfe-commits@lists.llvm.org> wrote:
>
>> Author: rsmith
>> Date: Wed Oct 19 20:20:00 2016
>> New Revision: 284685
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=284685=rev
>> Log:
>> Refactor and simplify Sema::FindCompositePointerType. No functionality
>> change intended.
>>
>> Modified:
>> cfe/trunk/lib/Sema/SemaExprCXX.cpp
>>
>> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
>> SemaExprCXX.cpp?rev=284685=284684=284685=diff
>> 
>> ==
>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Oct 19 20:20:00 2016
>> @@ -5520,7 +5520,7 @@ QualType Sema::CXXCheckConditionalOperan
>>  /// \brief Find a merged pointer type and convert the two expressions to
>> it.
>>  ///
>>  /// This finds the composite pointer type (or member pointer type) for
>> @p E1
>> -/// and @p E2 according to C++11 5.9p2. It converts both expressions to
>> this
>> +/// and @p E2 according to C++1z 5p14. It converts both expressions to
>> this
>>  /// type and returns it.
>>  /// It does not emit diagnostics.
>>  ///
>> @@ -5538,69 +5538,87 @@ QualType Sema::FindCompositePointerType(
>>  *NonStandardCompositeType = false;
>>
>>assert(getLangOpts().CPlusPlus && "This function assumes C++");
>> +
>> +  // C++1z [expr]p14:
>> +  //   The composite pointer type of two operands p1 and p2 having types
>> T1
>> +  //   and T2
>>QualType T1 = E1->getType(), T2 = E2->getType();
>>
>> -  

Re: r284685 - Refactor and simplify Sema::FindCompositePointerType. No functionality change intended.

2016-10-20 Thread Mike Aizatsky via cfe-commits
I think this breaks windows bot:

http://lab.llvm.org:8011/builders/sanitizer-windows/builds/30745/steps/build%20clang%20lld/logs/stdio

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.



On Wed, Oct 19, 2016 at 6:29 PM Richard Smith via cfe-commits <
cfe-commits@lists.llvm.org> wrote:

> Author: rsmith
> Date: Wed Oct 19 20:20:00 2016
> New Revision: 284685
>
> URL: http://llvm.org/viewvc/llvm-project?rev=284685=rev
> Log:
> Refactor and simplify Sema::FindCompositePointerType. No functionality
> change intended.
>
> Modified:
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=284685=284684=284685=diff
>
> ==
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Oct 19 20:20:00 2016
> @@ -5520,7 +5520,7 @@ QualType Sema::CXXCheckConditionalOperan
>  /// \brief Find a merged pointer type and convert the two expressions to
> it.
>  ///
>  /// This finds the composite pointer type (or member pointer type) for @p
> E1
> -/// and @p E2 according to C++11 5.9p2. It converts both expressions to
> this
> +/// and @p E2 according to C++1z 5p14. It converts both expressions to
> this
>  /// type and returns it.
>  /// It does not emit diagnostics.
>  ///
> @@ -5538,69 +5538,87 @@ QualType Sema::FindCompositePointerType(
>  *NonStandardCompositeType = false;
>
>assert(getLangOpts().CPlusPlus && "This function assumes C++");
> +
> +  // C++1z [expr]p14:
> +  //   The composite pointer type of two operands p1 and p2 having types
> T1
> +  //   and T2
>QualType T1 = E1->getType(), T2 = E2->getType();
>
> -  // C++11 5.9p2
> -  //   Pointer conversions and qualification conversions are performed on
> -  //   pointer operands to bring them to their composite pointer type. If
> -  //   one operand is a null pointer constant, the composite pointer type
> is
> -  //   std::nullptr_t if the other operand is also a null pointer
> constant 

r284685 - Refactor and simplify Sema::FindCompositePointerType. No functionality change intended.

2016-10-19 Thread Richard Smith via cfe-commits
Author: rsmith
Date: Wed Oct 19 20:20:00 2016
New Revision: 284685

URL: http://llvm.org/viewvc/llvm-project?rev=284685=rev
Log:
Refactor and simplify Sema::FindCompositePointerType. No functionality change 
intended.

Modified:
cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=284685=284684=284685=diff
==
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Oct 19 20:20:00 2016
@@ -5520,7 +5520,7 @@ QualType Sema::CXXCheckConditionalOperan
 /// \brief Find a merged pointer type and convert the two expressions to it.
 ///
 /// This finds the composite pointer type (or member pointer type) for @p E1
-/// and @p E2 according to C++11 5.9p2. It converts both expressions to this
+/// and @p E2 according to C++1z 5p14. It converts both expressions to this
 /// type and returns it.
 /// It does not emit diagnostics.
 ///
@@ -5538,69 +5538,87 @@ QualType Sema::FindCompositePointerType(
 *NonStandardCompositeType = false;
 
   assert(getLangOpts().CPlusPlus && "This function assumes C++");
+
+  // C++1z [expr]p14:
+  //   The composite pointer type of two operands p1 and p2 having types T1
+  //   and T2
   QualType T1 = E1->getType(), T2 = E2->getType();
 
-  // C++11 5.9p2
-  //   Pointer conversions and qualification conversions are performed on
-  //   pointer operands to bring them to their composite pointer type. If
-  //   one operand is a null pointer constant, the composite pointer type is
-  //   std::nullptr_t if the other operand is also a null pointer constant or,
-  //   if the other operand is a pointer, the type of the other operand.
-  if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
-  !T2->isAnyPointerType() && !T2->isMemberPointerType()) {
-if (T1->isNullPtrType() &&
-E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
-  E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();
-  return T1;
-}
-if (T2->isNullPtrType() &&
-E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
-  E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();
-  return T2;
-}
+  //   where at least one is a pointer or pointer to member type or
+  //   std::nullptr_t is:
+  bool T1IsPointerLike = T1->isAnyPointerType() || T1->isMemberPointerType() ||
+ T1->isNullPtrType();
+  bool T2IsPointerLike = T2->isAnyPointerType() || T2->isMemberPointerType() ||
+ T2->isNullPtrType();
+  if (!T1IsPointerLike && !T2IsPointerLike)
 return QualType();
-  }
 
-  if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
-if (T2->isMemberPointerType())
-  E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).get();
-else
-  E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).get();
-return T2;
-  }
-  if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
-if (T1->isMemberPointerType())
-  E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).get();
-else
-  E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).get();
+  //   - if both p1 and p2 are null pointer constants, std::nullptr_t;
+  // This can't actually happen, following the standard, but we also use this
+  // to implement the end of [expr.conv], which hits this case.
+  //
+  //   - if either p1 or p2 is a null pointer constant, T2 or T1, respectively;
+  if (T1IsPointerLike &&
+  E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+E2 = ImpCastExprToType(E2, T1, T1->isMemberPointerType()
+   ? CK_NullToMemberPointer
+   : CK_NullToPointer).get();
 return T1;
   }
+  if (T2IsPointerLike &&
+  E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+E1 = ImpCastExprToType(E1, T2, T2->isMemberPointerType()
+   ? CK_NullToMemberPointer
+   : CK_NullToPointer).get();
+return T2;
+  }
 
   // Now both have to be pointers or member pointers.
-  if ((!T1->isPointerType() && !T1->isMemberPointerType()) ||
-  (!T2->isPointerType() && !T2->isMemberPointerType()))
+  if (!T1IsPointerLike || !T2IsPointerLike)
 return QualType();
+  assert(!T1->isNullPtrType() && !T2->isNullPtrType() &&
+ "nullptr_t should be a null pointer constant");
 
-  //   Otherwise, of one of the operands has type "pointer to cv1 void," then
-  //   the other has type "pointer to cv2 T" and the composite pointer type is
-  //   "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
-  //   Otherwise, the composite pointer type is a pointer type similar to the
-  //   type of one of the operands, with a cv-qualification signature that is
-  //   the