diff --git include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticGroups.td
index 8811e6a..c880b0e 100644
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -33,6 +33,7 @@ def StringConversion : DiagGroup<"string-conversion">;
 def SignConversion : DiagGroup<"sign-conversion">;
 def BoolConversion : DiagGroup<"bool-conversion">;
 def IntConversion : DiagGroup<"int-conversion">;
+def UnusualNullConversion : DiagGroup<"unusual-null-conversion">;
 def NullConversion : DiagGroup<"null-conversion">;
 def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
 def CXXCompat: DiagGroup<"c++-compat">;
@@ -314,7 +315,8 @@ def Conversion : DiagGroup<"conversion",
                             StringConversion,
                             SignConversion,
                             BoolConversion,
-                            NullConversion,
+                            NullConversion, // NULL->non-pointer
+                            UnusualNullConversion, // (1-1)->pointer (etc)
                             IntConversion]>,
                  DiagCategory<"Value Conversion Issue">;
 
diff --git include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/DiagnosticSemaKinds.td
index eb8fcbb..c1bafdc 100644
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1888,6 +1888,9 @@ def warn_impcast_different_enum_types : Warning<
 def warn_impcast_bool_to_null_pointer : Warning<
     "initialization of pointer of type %0 to null from a constant boolean "
     "expression">, InGroup<BoolConversion>;
+def warn_unusual_null_pointer : Warning<
+    "initialization of pointer of type %0 to null from a non-trivial zero "
+    "expression">, InGroup<UnusualNullConversion>;
 def warn_impcast_null_pointer_to_integer : Warning<
     "implicit conversion of NULL constant to %0">,
     InGroup<NullConversion>;
diff --git include/clang/Sema/Sema.h include/clang/Sema/Sema.h
index bce285d..bc97675 100644
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5709,6 +5709,12 @@ public:
   /// diagnostics that will be suppressed.
   llvm::Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const;
 
+  /// \brief Determines whether we are currently in a context that
+  /// is not evaluated as per C++ [expr] p5.
+  bool isUnevaluatedContext() const {
+    return ExprEvalContexts.back().Context == Sema::Unevaluated;
+  }
+
   /// \brief RAII class used to determine whether SFINAE has
   /// trapped any errors that occur during template argument
   /// deduction.`
diff --git lib/Sema/SemaChecking.cpp lib/Sema/SemaChecking.cpp
index 73f9b01..152ba5f 100644
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -4721,7 +4721,7 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) {
 ///   conversion
 void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
   // Don't diagnose in unevaluated contexts.
-  if (ExprEvalContexts.back().Context == Sema::Unevaluated)
+  if (isUnevaluatedContext())
     return;
 
   // Don't diagnose for value- or type-dependent expressions.
diff --git lib/Sema/SemaExpr.cpp lib/Sema/SemaExpr.cpp
index 19259b3..46bff85 100644
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -584,8 +584,7 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
   //     is a prvalue for the temporary.
   // FIXME: add some way to gate this entire thing for correctness in
   // potentially potentially evaluated contexts.
-  if (getLangOpts().CPlusPlus && E->isGLValue() && 
-      ExprEvalContexts.back().Context != Unevaluated) {
+  if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext()) {
     ExprResult Temp = PerformCopyInitialization(
                        InitializedEntity::InitializeTemporary(E->getType()),
                                                 E->getExprLoc(),
@@ -2403,7 +2402,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
       // FIXME: Does the addition of const really only apply in
       // potentially-evaluated contexts? Since the variable isn't actually
       // captured in an unevaluated context, it seems that the answer is no.
-      if (ExprEvalContexts.back().Context != Sema::Unevaluated) {
+      if (!isUnevaluatedContext()) {
         QualType CapturedType = getCapturedDeclRefType(cast<VarDecl>(VD), Loc);
         if (!CapturedType.isNull())
           type = CapturedType;
@@ -10019,7 +10018,7 @@ namespace {
     // Error on DeclRefExprs referring to FieldDecls.
     ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
       if (isa<FieldDecl>(E->getDecl()) &&
-          SemaRef.ExprEvalContexts.back().Context != Sema::Unevaluated)
+          !SemaRef.isUnevaluatedContext())
         return SemaRef.Diag(E->getLocation(),
                             diag::err_invalid_non_static_member_use)
             << E->getDecl() << E->getSourceRange();
@@ -10043,11 +10042,11 @@ namespace {
 }
 
 ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) {
-  assert(ExprEvalContexts.back().Context == Unevaluated &&
+  assert(isUnevaluatedContext() &&
          "Should only transform unevaluated expressions");
   ExprEvalContexts.back().Context =
       ExprEvalContexts[ExprEvalContexts.size()-2].Context;
-  if (ExprEvalContexts.back().Context == Unevaluated)
+  if (isUnevaluatedContext())
     return E;
   return TransformToPE(*this).TransformExpr(E);
 }
diff --git lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.cpp
index bdf6f60..89ec184 100644
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -2562,13 +2562,21 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType,
 
   Kind = CK_BitCast;
 
-  if (!IsCStyleOrFunctionalCast &&
-      Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) &&
-      From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull))
-    DiagRuntimeBehavior(From->getExprLoc(), From,
-                        PDiag(diag::warn_impcast_bool_to_null_pointer)
-                          << ToType << From->getSourceRange());
-
+  if (!IsCStyleOrFunctionalCast && !FromType->isAnyPointerType()) {
+    Expr::NullPointerConstantKind NullKind =
+      From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull);
+    if (NullKind == Expr::NPCK_ZeroInteger) {
+      Expr *FromSansParens = From->IgnoreParens();
+      if (Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy))
+        DiagRuntimeBehavior(From->getExprLoc(), From,
+                            PDiag(diag::warn_impcast_bool_to_null_pointer)
+                              << ToType << From->getSourceRange());
+      else if (!isa<IntegerLiteral>(FromSansParens) &&
+               !isa<OpaqueValueExpr>(FromSansParens) && !isUnevaluatedContext())
+        Diag(From->getExprLoc(), diag::warn_unusual_null_pointer)
+          << ToType << From->getSourceRange();
+    }
+  }
   if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) {
     if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) {
       QualType FromPointeeType = FromPtrType->getPointeeType(),
diff --git lib/Sema/SemaType.cpp lib/Sema/SemaType.cpp
index 84e8a79..9b26c40 100644
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1084,7 +1084,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
 
   // If we are in an unevaluated context, like sizeof, skip adding a
   // qualification.
-  } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) {
+  } else if (S.isUnevaluatedContext()) {
     return type;
 
   // If that failed, give an error and recover using __strong.  __strong
diff --git test/SemaCXX/constant-expression-cxx11.cpp test/SemaCXX/constant-expression-cxx11.cpp
index 2b9a4ad..2e1219d 100644
--- test/SemaCXX/constant-expression-cxx11.cpp
+++ test/SemaCXX/constant-expression-cxx11.cpp
@@ -710,10 +710,18 @@ static_assert(&ok2 == pok2, "");
 static_assert((Base2*)(Derived*)(Base*)pb1 == pok2, "");
 static_assert((Derived*)(Base*)pb1 == (Derived*)pok2, "");
 
-constexpr Base *nullB = 42 - 6 * 7;
+constexpr Base *nullB = 42 - 6 * 7; // expected-warning {{initialization of pointer of type 'Class::Base *const' to null from a non-trivial zero expression}}
 static_assert((Bottom*)nullB == 0, "");
 static_assert((Derived*)nullB == 0, "");
 static_assert((void*)(Bottom*)nullB == (void*)(Derived*)nullB, "");
+Base * nullB2 = '\0'; // expected-warning {{initialization of pointer of type 'Class::Base *' to null from a non-trivial zero expression}}
+Base * nullB3 = (0);
+bool func(bool *b, char *c) {
+  // TODO: catch these cases too
+  if (b != false)
+    return c != '\0';
+  return false;
+}
 
 namespace ConversionOperators {
 
diff --git test/SemaCXX/lambda-expressions.cpp test/SemaCXX/lambda-expressions.cpp
index 198f8cf..05ed30e 100644
--- test/SemaCXX/lambda-expressions.cpp
+++ test/SemaCXX/lambda-expressions.cpp
@@ -117,16 +117,16 @@ namespace NullPtr {
 
     const int m = 0;
     [=] {
-      int &k = f(m); // a null pointer constant
+      int &k = f(m); // expected-warning{{initialization of pointer of type 'int *' to null from a non-trivial zero expression}}
     } ();
 
     [=] () -> bool {
-      int &k = f(m); // a null pointer constant
+      int &k = f(m); // expected-warning{{initialization of pointer of type 'int *' to null from a non-trivial zero expression}}
       return &m == 0;
     } ();
 
     [m] {
-      int &k = f(m); // a null pointer constant
+      int &k = f(m); // expected-warning{{initialization of pointer of type 'int *' to null from a non-trivial zero expression}}
     } ();
   }
 }
diff --git test/SemaTemplate/explicit-instantiation.cpp test/SemaTemplate/explicit-instantiation.cpp
index 13d76be..4fdaa58 100644
--- test/SemaTemplate/explicit-instantiation.cpp
+++ test/SemaTemplate/explicit-instantiation.cpp
@@ -14,7 +14,7 @@ struct X0 {
   T f0(T x) {
     return x + 1;  // expected-error{{invalid operands}}
   } 
-  T* f0(T*, T*) { return T(); }
+  T* f0(T*, T*) { return T(); } // expected-warning{{initialization of pointer of type 'int *' to null from a non-trivial zero expression}}
   
   template<typename U>
   T f0(T, U) { return T(); }
@@ -32,7 +32,7 @@ struct NotDefaultConstructible { // expected-note{{candidate constructor (the im
 template NotDefaultConstructible X0<NotDefaultConstructible>::value; // expected-note{{instantiation}}
 
 template int X0<int>::f0(int);
-template int* X0<int>::f0(int*, int*);
+template int* X0<int>::f0(int*, int*); // expected-note{{in instantiation of member function 'X0<int>::f0' requested here}}
 template int X0<int>::f0(int, float);
 
 template int X0<int>::f0(int) const; // expected-error{{does not refer}}
diff --git test/SemaTemplate/instantiate-member-class.cpp test/SemaTemplate/instantiate-member-class.cpp
index bb64276..a39789e 100644
--- test/SemaTemplate/instantiate-member-class.cpp
+++ test/SemaTemplate/instantiate-member-class.cpp
@@ -124,19 +124,20 @@ namespace rdar10397846 {
   {
     struct B
     {
-      struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+      struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
+                                             expected-warning{{initialization of pointer of type 'int *' to null from a non-trivial zero expression}}
     };
   };
 
   template<int N> void foo()
   {
-    class A<N>::B::C X; // expected-note{{in instantiation of member function}}
+    class A<N>::B::C X; // expected-note 2 {{in instantiation of member function}}
     int A<N+1>::B::C::*member = 0;
   }
 
   void bar()
   {
-    foo<0>();
+    foo<0>(); // expected-note{{in instantiation of function template}}
     foo<1>(); // expected-note{{in instantiation of function template}}
   }
 }
