Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -144,6 +144,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">; @@ -789,6 +790,7 @@ SelfMove, SizeofArrayArgument, SizeofArrayDecay, + DivSizeofPtr, StringPlusInt, Trigraphs, Uninitialized, Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -3294,6 +3294,10 @@ InGroup; 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, DefaultIgnore; + 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 @@ -8726,6 +8726,37 @@ << 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 || LUE->isArgumentType() || + RUE->getKind() != UETT_SizeOf) + return; + + QualType LHSTy; + QualType RHSTy; + LHSTy = LUE->getArgumentExpr()->IgnoreParens()->getType(); + + 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 +8787,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; } @@ -16599,4 +16632,4 @@ return new (Context) ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); -} +} \ No newline at end of file Index: test/Sema/div-sizeof-ptr.c =================================================================== --- test/Sema/div-sizeof-ptr.c +++ test/Sema/div-sizeof-ptr.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -verify -Wsizeof-pointer-div -fsyntax-only + +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}} + + int b1 = sizeof(int *) / sizeof(int); + int b2 = sizeof(p) / sizeof(p); + int b3 = sizeof(*q) / sizeof(q); + int b4 = sizeof(p) / sizeof(char); +}