Produce warning for performing pointer arithmetic on a null pointer.

Summary:
Test and produce warning for subtracting a pointer from null or subtracting
null from a pointer.  Reuse existing warning that this is undefined
behaviour.  Also add unit test for both warnings.

Reformat to satisfy clang-format.

Respond to review comments:  add additional test.

Respond to review comments:  Do not issue warning for nullptr - nullptr
in C++.

Fix indenting to satisfy clang-format.

Respond to review comments:  Add C++ tests.

Author: Jamie Schmeiser <schmeise@ca.ibm.com>
Reviewed By: efriedma (Eli Friedman), nickdesaulniers (Nick Desaulniers)
Differential Revision: https://reviews.llvm.org/D98798
This commit is contained in:
Jamie Schmeiser 2021-05-11 11:29:50 -04:00
parent 4eff946947
commit dfc1e31d49
3 changed files with 22 additions and 1 deletions

View File

@ -10779,7 +10779,17 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
LHS.get(), RHS.get()))
return QualType();
// FIXME: Add warnings for nullptr - ptr.
bool LHSIsNullPtr = LHS.get()->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull);
bool RHSIsNullPtr = RHS.get()->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull);
// Subtracting nullptr or from nullptr should produce
// a warning expect nullptr - nullptr is valid in C++ [expr.add]p7
if (LHSIsNullPtr && (!getLangOpts().CPlusPlus || !RHSIsNullPtr))
diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
if (RHSIsNullPtr && (!getLangOpts().CPlusPlus || !LHSIsNullPtr))
diagnoseArithmeticOnNullPointer(*this, Loc, RHS.get(), false);
// The pointee type may have zero size. As an extension, a structure or
// union may have zero size or an array may have zero length. In this

View File

@ -29,4 +29,7 @@ void a(S* b, void* c) {
// Cases that don't match the GNU inttoptr idiom get a different warning.
f = (char*)0 - i; // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
int *g = (int*)0 + i; // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
f = (char*)((char*)0 - f); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
f = (char*)(f - (char*)0); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
f = (char*)((char*)0 - (char*)0); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}} expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
}

View File

@ -0,0 +1,8 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -Wextra -std=c++11
void a() {
char *f = (char*)0;
f = (char*)((char*)0 - f); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
f = (char*)(f - (char*)0); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
f = (char*)((char*)0 - (char*)0); // valid in C++
}