summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2016-05-14 17:44:14 +0000
committerNick Lewycky <nicholas@mxc.ca>2016-05-14 17:44:14 +0000
commit2eeddfb1efc8200468725c50647e3b250b28e902 (patch)
tree1c8b72219c1fce87621af755a546b18ce7ef6e63
parent962b2cda9cfa93b48aa044783209a3939d66b73d (diff)
downloadbcm5719-llvm-2eeddfb1efc8200468725c50647e3b250b28e902.tar.gz
bcm5719-llvm-2eeddfb1efc8200468725c50647e3b250b28e902.zip
Warn when a reference is bound to an empty l-value (dereferenced null pointer).
llvm-svn: 269572
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/Sema/SemaInit.cpp15
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp4
-rw-r--r--clang/test/Parser/cxx-casting.cpp2
-rw-r--r--clang/test/SemaCXX/cstyle-cast.cpp6
-rw-r--r--clang/test/SemaCXX/functional-cast.cpp6
-rw-r--r--clang/test/SemaCXX/new-delete.cpp4
-rw-r--r--clang/test/SemaCXX/static-cast.cpp6
8 files changed, 34 insertions, 15 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ba6db97c136..322427862f6 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5371,7 +5371,11 @@ def ext_typecheck_indirection_through_void_pointer : ExtWarn<
"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<
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 3563bf7b184..c162007349c 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6168,6 +6168,20 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
<< 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: {
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
index dc2c209af26..b8504d49065 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
@@ -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
diff --git a/clang/test/Parser/cxx-casting.cpp b/clang/test/Parser/cxx-casting.cpp
index 43885bff27a..b1ae591865e 100644
--- a/clang/test/Parser/cxx-casting.cpp
+++ b/clang/test/Parser/cxx-casting.cpp
@@ -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;
diff --git a/clang/test/SemaCXX/cstyle-cast.cpp b/clang/test/SemaCXX/cstyle-cast.cpp
index afac6a137ec..2327d7b51d9 100644
--- a/clang/test/SemaCXX/cstyle-cast.cpp
+++ b/clang/test/SemaCXX/cstyle-cast.cpp
@@ -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
diff --git a/clang/test/SemaCXX/functional-cast.cpp b/clang/test/SemaCXX/functional-cast.cpp
index 9db95e80d03..216ee240c83 100644
--- a/clang/test/SemaCXX/functional-cast.cpp
+++ b/clang/test/SemaCXX/functional-cast.cpp
@@ -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)();
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 7bc724b2101..e96603d69e1 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -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}}
}
}
diff --git a/clang/test/SemaCXX/static-cast.cpp b/clang/test/SemaCXX/static-cast.cpp
index b3fe49a88c6..ff47c0bb4dc 100644
--- a/clang/test/SemaCXX/static-cast.cpp
+++ b/clang/test/SemaCXX/static-cast.cpp
@@ -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);
OpenPOWER on IntegriCloud