Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5365,6 +5365,8 @@ InGroup>; def warn_indirection_through_null : Warning< "indirection of non-volatile null pointer will be deleted, not trap">, InGroup; +def warn_binding_null_to_reference : Warning< + "binding null pointer to reference has undefined behavior">, InGroup; def note_indirection_through_null : Note< "consider using __builtin_trap() or qualifying pointer with 'volatile'">; def warn_pointer_indirection_from_incompatible_type : Warning< Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -6193,6 +6193,20 @@ << FixItHint::CreateRemoval(SourceRange(RParen, RParen)); } +static void CheckForNullPointerDereference(Sema &S, const Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, this is + // undefined behavior, so warn about it. This only handles the pattern + // "*null", which is a very syntactic check. + if (const UnaryOperator *UO = dyn_cast(E->IgnoreParenCasts())) + if (UO->getOpcode() == UO_Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) { + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_binding_null_to_reference) + << UO->getSubExpr()->getSourceRange()); + } +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -6445,6 +6459,7 @@ /*IsInitializerList=*/false, ExtendingEntity->getDecl()); + CheckForNullPointerDereference(S, CurInit.get()); break; case SK_BindReferenceToTemporary: { Index: test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp =================================================================== --- test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp +++ test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp @@ -11,7 +11,7 @@ template struct bogus_override_if_virtual : public T { - bogus_override_if_virtual() : T(*(T*)0) { } + bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding null pointer to reference has undefined behavior}} int operator()() const; }; @@ -36,7 +36,7 @@ lv(); // expected-error{{no matching function for call to object of type}} mlv(); // expected-error{{no matching function for call to object of type}} - bogus_override_if_virtual bogus; + bogus_override_if_virtual bogus; // expected-note{{in instantiation of member function 'bogus_override_if_virtual<(lambda}} } // Core issue 974: default arguments (8.3.6) may be specified in the Index: test/Parser/cxx-casting.cpp =================================================================== --- test/Parser/cxx-casting.cpp +++ test/Parser/cxx-casting.cpp @@ -37,7 +37,7 @@ // This was being incorrectly tentatively parsed. namespace test1 { template class A {}; // expected-note 2{{here}} - void foo() { A(*(A*)0); } + void foo() { A(*(A*)0); } // expected-warning {{binding null pointer to reference has undefined behavior}} } typedef char* c; Index: test/SemaCXX/cstyle-cast.cpp =================================================================== --- test/SemaCXX/cstyle-cast.cpp +++ test/SemaCXX/cstyle-cast.cpp @@ -84,11 +84,11 @@ (void)(void*)((int*)0); (void)(volatile const void*)((const int*)0); (void)(A*)((B*)0); - (void)(A&)(*((B*)0)); + (void)(A&)(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(const B*)((C1*)0); - (void)(B&)(*((C1*)0)); + (void)(B&)(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(A*)((D*)0); - (void)(const A&)(*((D*)0)); + (void)(const A&)(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)(int B::*)((int A::*)0); (void)(void (B::*)())((void (A::*)())0); (void)(A*)((E*)0); // C-style cast ignores access control Index: test/SemaCXX/functional-cast.cpp =================================================================== --- test/SemaCXX/functional-cast.cpp +++ test/SemaCXX/functional-cast.cpp @@ -126,14 +126,14 @@ typedef A *Ap; (void)Ap((B*)0); typedef A &Ar; - (void)Ar(*((B*)0)); + (void)Ar(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef const B *cBp; (void)cBp((C1*)0); typedef B &Br; - (void)Br(*((C1*)0)); + (void)Br(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)Ap((D*)0); typedef const A &cAr; - (void)cAr(*((D*)0)); + (void)cAr(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} typedef int B::*Bmp; (void)Bmp((int A::*)0); typedef void (B::*Bmfp)(); Index: test/SemaCXX/new-delete.cpp =================================================================== --- test/SemaCXX/new-delete.cpp +++ test/SemaCXX/new-delete.cpp @@ -444,11 +444,11 @@ template void tfn() { - new (*(PlacementArg*)0) T[1]; + new (*(PlacementArg*)0) T[1]; // expected-warning 2 {{binding null pointer to reference has undefined behavior}} } void fn() { - tfn(); + tfn(); // expected-note {{in instantiation of function template specialization 'r150682::tfn' requested here}} } } Index: test/SemaCXX/static-cast.cpp =================================================================== --- test/SemaCXX/static-cast.cpp +++ test/SemaCXX/static-cast.cpp @@ -43,11 +43,11 @@ (void)static_cast((int*)0); (void)static_cast((const int*)0); (void)static_cast((B*)0); - (void)static_cast(*((B*)0)); + (void)static_cast(*((B*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((C1*)0); - (void)static_cast(*((C1*)0)); + (void)static_cast(*((C1*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((D*)0); - (void)static_cast(*((D*)0)); + (void)static_cast(*((D*)0)); // expected-warning {{binding null pointer to reference has undefined behavior}} (void)static_cast((int A::*)0); (void)static_cast((void (A::*)())0);