Skip to content

Commit dfc1e31

Browse files
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 <[email protected]> Reviewed By: efriedma (Eli Friedman), nickdesaulniers (Nick Desaulniers) Differential Revision: https://reviews.llvm.org/D98798
1 parent 4eff946 commit dfc1e31

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

clang/lib/Sema/SemaExpr.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10779,7 +10779,17 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
1077910779
LHS.get(), RHS.get()))
1078010780
return QualType();
1078110781

10782-
// FIXME: Add warnings for nullptr - ptr.
10782+
bool LHSIsNullPtr = LHS.get()->IgnoreParenCasts()->isNullPointerConstant(
10783+
Context, Expr::NPC_ValueDependentIsNotNull);
10784+
bool RHSIsNullPtr = RHS.get()->IgnoreParenCasts()->isNullPointerConstant(
10785+
Context, Expr::NPC_ValueDependentIsNotNull);
10786+
10787+
// Subtracting nullptr or from nullptr should produce
10788+
// a warning expect nullptr - nullptr is valid in C++ [expr.add]p7
10789+
if (LHSIsNullPtr && (!getLangOpts().CPlusPlus || !RHSIsNullPtr))
10790+
diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
10791+
if (RHSIsNullPtr && (!getLangOpts().CPlusPlus || !LHSIsNullPtr))
10792+
diagnoseArithmeticOnNullPointer(*this, Loc, RHS.get(), false);
1078310793

1078410794
// The pointee type may have zero size. As an extension, a structure or
1078510795
// union may have zero size or an array may have zero length. In this

clang/test/Sema/pointer-addition.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,7 @@ void a(S* b, void* c) {
2929
// Cases that don't match the GNU inttoptr idiom get a different warning.
3030
f = (char*)0 - i; // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
3131
int *g = (int*)0 + i; // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
32+
f = (char*)((char*)0 - f); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
33+
f = (char*)(f - (char*)0); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
34+
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}}
3235
}

clang/test/Sema/pointer-addition.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %clang_cc1 %s -fsyntax-only -verify -pedantic -Wextra -std=c++11
2+
3+
void a() {
4+
char *f = (char*)0;
5+
f = (char*)((char*)0 - f); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
6+
f = (char*)(f - (char*)0); // expected-warning {{performing pointer arithmetic on a null pointer has undefined behavior}}
7+
f = (char*)((char*)0 - (char*)0); // valid in C++
8+
}

0 commit comments

Comments
 (0)