Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -142,6 +142,7 @@ def : DiagGroup<"discard-qual">; def DivZero : DiagGroup<"division-by-zero">; def : DiagGroup<"div-by-zero", [DivZero]>; +def DivSizeofPtr : DiagGroup<"sizeof-pointer-div">; def DocumentationHTML : DiagGroup<"documentation-html">; def DocumentationUnknownCommand : DiagGroup<"documentation-unknown-command">; @@ -785,6 +786,7 @@ SelfMove, SizeofArrayArgument, SizeofArrayDecay, + DivSizeofPtr, StringPlusInt, Trigraphs, Uninitialized, Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -3291,6 +3291,10 @@ InGroup; def note_reference_is_return_value : Note<"%0 returns a reference">; +def warn_division_sizeof_ptr : Warning< + "division produces the incorrect number of array elements">, + InGroup; + def note_function_warning_silence : Note< "prefix with the address-of operator to silence this warning">; def note_function_to_function_call : Note< Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -8670,6 +8670,41 @@ << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); } +static void DiagnoseDivisionSizeofPointer(Sema &S, Expr *LHS, Expr *RHS, + SourceLocation Loc) { + UnaryExprOrTypeTraitExpr *LUE = + dyn_cast_or_null(LHS); + UnaryExprOrTypeTraitExpr *RUE = + dyn_cast_or_null(RHS); + + if (!LUE || !RUE) + return; + if (LUE->getKind() != UETT_SizeOf || RUE->getKind() != UETT_SizeOf) + return; + + QualType LHSTy; + QualType RHSTy; + if (LUE->isArgumentType()) + return; + + LHS = LUE->getArgumentExpr()->IgnoreParens(); + LHSTy = LHS->getType(); + + if (RUE->isArgumentType()) { + RHSTy = RUE->getArgumentType(); + } else { + RHS = RUE->getArgumentExpr()->IgnoreParens(); + RHSTy = RHS->getType(); + } + + if (!LHSTy->isPointerType() || RHSTy->isPointerType()) + return; + if (LHSTy->getPointeeType() != RHSTy) + return; + + S.Diag(Loc, diag::warn_division_sizeof_ptr) << LHS->getSourceRange(); +} + static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsDiv) { @@ -8700,8 +8735,10 @@ 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; } Index: test/Sema/div-sizeof-ptr.c =================================================================== --- test/Sema/div-sizeof-ptr.c +++ test/Sema/div-sizeof-ptr.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -verify -Wsizeof-pointer-div -fsyntax-only + +void test(int *p, int **q) { + int a = sizeof(p) / sizeof(*p); // expected-warning {{division produces the incorrect number of array elements}} + int b = sizeof p / sizeof *p; // expected-warning {{division produces the incorrect number of array elements}} + int c = sizeof(*q) / sizeof(**q); // expected-warning {{division produces the incorrect number of array elements}} + int d = sizeof(p) / sizeof(int); // expected-warning {{division produces the incorrect number of array elements}} + + int e = sizeof(int *) / sizeof(int); + int f = sizeof(p) / sizeof(p); + int g = sizeof(*q) / sizeof(q); +}