r269572 - Warn when a reference is bound to an empty l-value (dereferenced null pointer).

Nick Lewycky via cfe-commits cfe-commits at lists.llvm.org
Sat May 14 10:44:14 PDT 2016


Author: nicholas
Date: Sat May 14 12:44:14 2016
New Revision: 269572

URL: http://llvm.org/viewvc/llvm-project?rev=269572&view=rev
Log:
Warn when a reference is bound to an empty l-value (dereferenced null pointer).

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
    cfe/trunk/test/Parser/cxx-casting.cpp
    cfe/trunk/test/SemaCXX/cstyle-cast.cpp
    cfe/trunk/test/SemaCXX/functional-cast.cpp
    cfe/trunk/test/SemaCXX/new-delete.cpp
    cfe/trunk/test/SemaCXX/static-cast.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat May 14 12:44:14 2016
@@ -5371,7 +5371,11 @@ def ext_typecheck_indirection_through_vo
   "ISO C++ does not allow indirection on operand of type %0">,
   InGroup<DiagGroup<"void-ptr-dereference">>;
 def warn_indirection_through_null : Warning<
-  "indirection of non-volatile null pointer will be deleted, not trap">, InGroup<NullDereference>;
+  "indirection of non-volatile null pointer will be deleted, not trap">,
+  InGroup<NullDereference>;
+def warn_binding_null_to_reference : Warning<
+  "binding dereferenced null pointer to reference has undefined behavior">,
+  InGroup<NullDereference>;
 def note_indirection_through_null : Note<
   "consider using __builtin_trap() or qualifying pointer with 'volatile'">;
 def warn_pointer_indirection_from_incompatible_type : Warning<

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat May 14 12:44:14 2016
@@ -6168,6 +6168,20 @@ static void CheckMoveOnConstruction(Sema
       << 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<UnaryOperator>(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,
@@ -6420,6 +6434,7 @@ InitializationSequence::Perform(Sema &S,
                                   /*IsInitializerList=*/false,
                                   ExtendingEntity->getDecl());
 
+      CheckForNullPointerDereference(S, CurInit.get());
       break;
 
     case SK_BindReferenceToTemporary: {

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp Sat May 14 12:44:14 2016
@@ -11,7 +11,7 @@ void test_attributes() {
 
 template<typename T>
 struct bogus_override_if_virtual : public T {
-  bogus_override_if_virtual() : T(*(T*)0) { }
+  bogus_override_if_virtual() : T(*(T*)0) { } // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
   int operator()() const;
 };
 
@@ -36,7 +36,7 @@ void test_quals() {
   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<decltype(l)> bogus;
+  bogus_override_if_virtual<decltype(l)> 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

Modified: cfe/trunk/test/Parser/cxx-casting.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-casting.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-casting.cpp (original)
+++ cfe/trunk/test/Parser/cxx-casting.cpp Sat May 14 12:44:14 2016
@@ -37,7 +37,7 @@ char postfix_expr_test()
 // This was being incorrectly tentatively parsed.
 namespace test1 {
   template <class T> class A {}; // expected-note 2{{here}}
-  void foo() { A<int>(*(A<int>*)0); }
+  void foo() { A<int>(*(A<int>*)0); } // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
 }
 
 typedef char* c;

Modified: cfe/trunk/test/SemaCXX/cstyle-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cstyle-cast.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cstyle-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/cstyle-cast.cpp Sat May 14 12:44:14 2016
@@ -84,11 +84,11 @@ void t_529_2()
   (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 dereferenced null pointer to reference has undefined behavior}}
   (void)(const B*)((C1*)0);
-  (void)(B&)(*((C1*)0));
+  (void)(B&)(*((C1*)0)); // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
   (void)(A*)((D*)0);
-  (void)(const A&)(*((D*)0));
+  (void)(const A&)(*((D*)0)); // expected-warning {{binding dereferenced 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

Modified: cfe/trunk/test/SemaCXX/functional-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/functional-cast.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/functional-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/functional-cast.cpp Sat May 14 12:44:14 2016
@@ -126,14 +126,14 @@ void t_529_2()
   typedef A *Ap;
   (void)Ap((B*)0);
   typedef A &Ar;
-  (void)Ar(*((B*)0));
+  (void)Ar(*((B*)0)); // expected-warning {{binding dereferenced 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 dereferenced 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 dereferenced null pointer to reference has undefined behavior}}
   typedef int B::*Bmp;
   (void)Bmp((int A::*)0);
   typedef void (B::*Bmfp)();

Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Sat May 14 12:44:14 2016
@@ -444,11 +444,11 @@ namespace r150682 {
 
   template<typename X>
   void tfn() {
-    new (*(PlacementArg*)0) T[1];
+    new (*(PlacementArg*)0) T[1]; // expected-warning 2 {{binding dereferenced null pointer to reference has undefined behavior}}
   }
 
   void fn() {
-    tfn<int>();
+    tfn<int>();  // expected-note {{in instantiation of function template specialization 'r150682::tfn<int>' requested here}}
   }
 
 }

Modified: cfe/trunk/test/SemaCXX/static-cast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-cast.cpp?rev=269572&r1=269571&r2=269572&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-cast.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-cast.cpp Sat May 14 12:44:14 2016
@@ -43,11 +43,11 @@ void t_529_2()
   (void)static_cast<void*>((int*)0);
   (void)static_cast<volatile const void*>((const int*)0);
   (void)static_cast<A*>((B*)0);
-  (void)static_cast<A&>(*((B*)0));
+  (void)static_cast<A&>(*((B*)0)); // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
   (void)static_cast<const B*>((C1*)0);
-  (void)static_cast<B&>(*((C1*)0));
+  (void)static_cast<B&>(*((C1*)0)); // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
   (void)static_cast<A*>((D*)0);
-  (void)static_cast<const A&>(*((D*)0));
+  (void)static_cast<const A&>(*((D*)0)); // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
   (void)static_cast<int B::*>((int A::*)0);
   (void)static_cast<void (B::*)()>((void (A::*)())0);
 




More information about the cfe-commits mailing list