aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bolvansky <david.bolvansky@gmail.com>2018-11-01 16:26:10 +0000
committerDavid Bolvansky <david.bolvansky@gmail.com>2018-11-01 16:26:10 +0000
commitb8dc05260c7da2260c0f48a14f880b062785d09f (patch)
tree967290019519f1ff70549f0e31ec29b7c6e98fae
parentd686dbbc7c24a81a46f61733d48df866f2874e24 (diff)
downloadllvm-b8dc05260c7da2260c0f48a14f880b062785d09f.zip
llvm-b8dc05260c7da2260c0f48a14f880b062785d09f.tar.gz
llvm-b8dc05260c7da2260c0f48a14f880b062785d09f.tar.bz2
[Diagnostics] Implement -Wsizeof-pointer-div
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
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/lib/Sema/SemaExpr.cpp32
-rw-r--r--clang/test/Sema/div-sizeof-ptr.cpp28
3 files changed, 62 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3dc3605..8403278 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ecda5be..d7fc1aa 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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) {
@@ -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;
}
@@ -16603,4 +16631,4 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
-}
+} \ No newline at end of file
diff --git a/clang/test/Sema/div-sizeof-ptr.cpp b/clang/test/Sema/div-sizeof-ptr.cpp
new file mode 100644
index 0000000..4a411ff6b
--- /dev/null
+++ b/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);
+}