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 @@ -5862,6 +5862,8 @@ LangAS DestAS = DestTy->getPointeeType().getAddressSpace(); if (SrcAS != DestAS) return CK_AddressSpaceConversion; + if (Context.hasCvrSimilarType(SrcTy, DestTy)) + return CK_NoOp; return CK_BitCast; } case Type::STK_BlockPointer: @@ -7762,7 +7764,12 @@ if (isa(RHSType)) { LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace(); - Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; + if (AddrSpaceL != AddrSpaceR) + Kind = CK_AddressSpaceConversion; + else if (Context.hasCvrSimilarType(RHSType, LHSType)) + Kind = CK_NoOp; + else + Kind = CK_BitCast; return checkPointerTypesForAssignment(*this, LHSType, RHSType); } @@ -8670,6 +8677,39 @@ << 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; + 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 +8740,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; } @@ -13428,6 +13470,7 @@ PopExpressionEvaluationContext(); BlockScopeInfo *BSI = cast(FunctionScopes.back()); + BlockDecl *BD = BSI->TheDecl; if (BSI->HasImplicitReturnType) deduceClosureReturnType(*BSI); @@ -13438,7 +13481,7 @@ if (!BSI->ReturnType.isNull()) RetTy = BSI->ReturnType; - bool NoReturn = BSI->TheDecl->hasAttr(); + bool NoReturn = BD->hasAttr(); QualType BlockTy; // Set the captured variables on the block. @@ -13451,7 +13494,7 @@ Cap.isNested(), Cap.getInitExpr()); Captures.push_back(NewCap); } - BSI->TheDecl->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); + BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0); // If the user wrote a function type in some form, try to use that. if (!BSI->FunctionType.isNull()) { @@ -13488,7 +13531,7 @@ BlockTy = Context.getFunctionType(RetTy, None, EPI); } - DiagnoseUnusedParameters(BSI->TheDecl->parameters()); + DiagnoseUnusedParameters(BD->parameters()); BlockTy = Context.getBlockPointerType(BlockTy); // If needed, diagnose invalid gotos and switches in the block. @@ -13496,19 +13539,19 @@ !PP.isCodeCompletionEnabled()) DiagnoseInvalidJumps(cast(Body)); - BSI->TheDecl->setBody(cast(Body)); + BD->setBody(cast(Body)); if (Body && getCurFunction()->HasPotentialAvailabilityViolations) - DiagnoseUnguardedAvailabilityViolations(BSI->TheDecl); + DiagnoseUnguardedAvailabilityViolations(BD); // Try to apply the named return value optimization. We have to check again // if we can do this, though, because blocks keep return statements around // to deduce an implicit return type. if (getLangOpts().CPlusPlus && RetTy->isRecordType() && - !BSI->TheDecl->isDependentContext()) + !BD->isDependentContext()) computeNRVO(Body, BSI); - BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); + BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy); AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result); @@ -13531,7 +13574,7 @@ } if (getCurFunction()) - getCurFunction()->addBlock(BSI->TheDecl); + getCurFunction()->addBlock(BD); return Result; } @@ -16533,4 +16576,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,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); +}