mirror of https://github.com/microsoft/clang.git
Warn when a reference is bound to an empty l-value (dereferenced null pointer).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@269572 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d5bb834945
commit
774ff762b3
|
@ -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<
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)();
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue