Skip to content

Commit

Permalink
[Diagnostics] Implement -Wsizeof-pointer-div
Browse files Browse the repository at this point in the history
Summary:
void test(int *arr) {
    int arr_len = sizeof(arr) / sizeof(*arr);  // warn, incorrect way to compute number of array elements
}

Enabled under -Wall (same behaviour as GCC)

Reviewers: rsmith, MTC, aaron.ballman

Reviewed By: aaron.ballman

Subscribers: MTC, thakis, jfb, cfe-commits

Differential Revision: https://reviews.llvm.org/D52949

llvm-svn: 345847
  • Loading branch information
davidbolvansky committed Nov 1, 2018
1 parent d686dbb commit b8dc052
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -3294,6 +3294,10 @@ def warn_address_of_reference_null_compare : Warning<
InGroup<TautologicalUndefinedCompare>;
def note_reference_is_return_value : Note<"%0 returns a reference">;

def warn_division_sizeof_ptr : Warning<
"'%0' will return the size of the pointer, not the array itself">,
InGroup<DiagGroup<"sizeof-pointer-div">>;

def note_function_warning_silence : Note<
"prefix with the address-of operator to silence this warning">;
def note_function_to_function_call : Note<
Expand Down
32 changes: 30 additions & 2 deletions clang/lib/Sema/SemaExpr.cpp
Expand Up @@ -8726,6 +8726,32 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}

static void DiagnoseDivisionSizeofPointer(Sema &S, Expr *LHS, Expr *RHS,
SourceLocation Loc) {
const auto *LUE = dyn_cast<UnaryExprOrTypeTraitExpr>(LHS);
const auto *RUE = dyn_cast<UnaryExprOrTypeTraitExpr>(RHS);
if (!LUE || !RUE)
return;
if (LUE->getKind() != UETT_SizeOf || LUE->isArgumentType() ||
RUE->getKind() != UETT_SizeOf)
return;

QualType LHSTy = LUE->getArgumentExpr()->IgnoreParens()->getType();
QualType RHSTy;

if (RUE->isArgumentType())
RHSTy = RUE->getArgumentType();
else
RHSTy = RUE->getArgumentExpr()->IgnoreParens()->getType();

if (!LHSTy->isPointerType() || RHSTy->isPointerType())
return;
if (LHSTy->getPointeeType() != RHSTy)
return;

S.Diag(Loc, diag::warn_division_sizeof_ptr) << LHS << LHS->getSourceRange();
}

static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc, bool IsDiv) {
Expand Down Expand Up @@ -8756,8 +8782,10 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,

if (compType.isNull() || !compType->isArithmeticType())
return InvalidOperands(Loc, LHS, RHS);
if (IsDiv)
if (IsDiv) {
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
DiagnoseDivisionSizeofPointer(*this, LHS.get(), RHS.get(), Loc);
}
return compType;
}

Expand Down Expand Up @@ -16603,4 +16631,4 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(

return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
}
}
28 changes: 28 additions & 0 deletions clang/test/Sema/div-sizeof-ptr.cpp
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 %s -verify -Wsizeof-pointer-div -fsyntax-only

template <typename Ty, int N>
int f(Ty (&Array)[N]) {
return sizeof(Array) / sizeof(Ty); // Should not warn
}

void test(int *p, int **q) {
int a1 = sizeof(p) / sizeof(*p); // expected-warning {{'sizeof (p)' will return the size of the pointer, not the array itself}}
int a2 = sizeof p / sizeof *p; // expected-warning {{'sizeof p' will return the size of the pointer, not the array itself}}
int a3 = sizeof(*q) / sizeof(**q); // expected-warning {{'sizeof (*q)' will return the size of the pointer, not the array itself}}
int a4 = sizeof(p) / sizeof(int); // expected-warning {{'sizeof (p)' will return the size of the pointer, not the array itself}}
int a5 = sizeof(p) / sizeof(p[0]); // expected-warning {{'sizeof (p)' will return the size of the pointer, not the array itself}}

// Should not warn
int b1 = sizeof(int *) / sizeof(int);
int b2 = sizeof(p) / sizeof(p);
int b3 = sizeof(*q) / sizeof(q);
int b4 = sizeof(p) / sizeof(char);

int arr[10];
int b5 = sizeof(arr) / sizeof(*arr);
int b6 = sizeof(arr) / sizeof(arr[0]);
int b7 = sizeof(arr) / sizeof(int);

int arr2[10][12];
int b8 = sizeof(arr2) / sizeof(*arr2);
}

0 comments on commit b8dc052

Please sign in to comment.