diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -51,7 +51,8 @@ Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- ... +- -Wpointer-to-int-cast is a new warning group. This group warns about C-style + casts of pointers to a integer type too small to hold all possible values. Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -836,6 +836,9 @@ def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">; def IntToPointerCast : DiagGroup<"int-to-pointer-cast", [IntToVoidPointerCast]>; +def VoidPointerToIntCast : DiagGroup<"void-pointer-to-int-cast">; +def PointerToIntCast : DiagGroup<"pointer-to-int-cast", + [VoidPointerToIntCast]>; def Move : DiagGroup<"move", [ PessimizingMove, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3658,6 +3658,15 @@ def warn_int_to_void_pointer_cast : Warning< "cast to %1 from smaller integer type %0">, InGroup; +def warn_pointer_to_int_cast : Warning< + "cast to smaller integer type %1 from %0">, + InGroup; +def warn_void_pointer_to_int_cast : Warning< + "cast to smaller integer type %1 from %0">, + InGroup; +def ext_ms_pointer_to_int_cast : ExtWarn< + "cast to smaller integer type %1 from %0 is a Microsoft extension">, +InGroup; def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">, diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1961,7 +1961,7 @@ << FD << DstCCName << FixItHint::CreateInsertion(NameLoc, CCAttrText); } -static void checkIntToPointerCast(bool CStyle, SourceLocation Loc, +static void checkIntToPointerCast(bool CStyle, const SourceRange &OpRange, const Expr *SrcExpr, QualType DestType, Sema &Self) { QualType SrcType = SrcExpr->getType(); @@ -1983,7 +1983,7 @@ unsigned Diag = DestType->isVoidPointerType() ? diag::warn_int_to_void_pointer_cast : diag::warn_int_to_pointer_cast; - Self.Diag(Loc, Diag) << SrcType << DestType; + Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange; } } @@ -2218,8 +2218,7 @@ if (SrcType->isIntegralOrEnumerationType()) { assert(destIsPtr && "One type must be a pointer"); - checkIntToPointerCast(CStyle, OpRange.getBegin(), SrcExpr.get(), DestType, - Self); + checkIntToPointerCast(CStyle, OpRange, SrcExpr.get(), DestType, Self); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not @@ -2752,8 +2751,8 @@ SrcExpr = ExprError(); return; } - checkIntToPointerCast(/* CStyle */ true, OpRange.getBegin(), SrcExpr.get(), - DestType, Self); + checkIntToPointerCast(/* CStyle */ true, OpRange, SrcExpr.get(), DestType, + Self); } else if (!SrcType->isArithmeticType()) { if (!DestType->isIntegralType(Self.Context) && DestType->isArithmeticType()) { @@ -2763,6 +2762,21 @@ SrcExpr = ExprError(); return; } + + if ((Self.Context.getTypeSize(SrcType) > + Self.Context.getTypeSize(DestType))) { + // C 6.3.2.3p6: Any pointer type may be converted to an integer type. + // Except as previously specified, the result is implementation-defined. + // If the result cannot be represented in the integer type, the behavior + // is undefined. The result need not be in the range of values of any + // integer type. + unsigned Diag = Self.getLangOpts().MicrosoftExt + ? diag::ext_ms_pointer_to_int_cast + : SrcType->isVoidPointerType() + ? diag::warn_void_pointer_to_int_cast + : diag::warn_pointer_to_int_cast; + Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange; + } } if (Self.getLangOpts().OpenCL && diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c --- a/clang/test/Analysis/bstring.c +++ b/clang/test/Analysis/bstring.c @@ -523,6 +523,6 @@ }; void nocrash_on_locint_offset(void *addr, void* from, struct S s) { - int iAdd = (int) addr; + size_t iAdd = (size_t) addr; memcpy(((void *) &(s.f)), from, iAdd); } diff --git a/clang/test/Analysis/casts.c b/clang/test/Analysis/casts.c --- a/clang/test/Analysis/casts.c +++ b/clang/test/Analysis/casts.c @@ -1,7 +1,7 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -w %s -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -verify -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -Wno-pointer-to-int-cast -verify -DEAGERLY_ASSUME=1 -w %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin9 -analyzer-checker=core,alpha.core,debug.ExprInspection -Wno-pointer-to-int-cast -verify -DEAGERLY_ASSUME=1 -DBIT32=1 -w %s extern void clang_analyzer_eval(_Bool); diff --git a/clang/test/Analysis/misc-ps.c b/clang/test/Analysis/misc-ps.c --- a/clang/test/Analysis/misc-ps.c +++ b/clang/test/Analysis/misc-ps.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -disable-free -analyzer-checker=core,deadcode,debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -disable-free -analyzer-checker=core,deadcode,debug.ExprInspection -Wno-pointer-to-int-cast -verify %s void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m --- a/clang/test/Analysis/misc-ps.m +++ b/clang/test/Analysis/misc-ps.m @@ -1,6 +1,6 @@ // NOTE: Use '-fobjc-gc' to test the analysis being run twice, and multiple reports are not issued. -// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,alpha.core,osx.cocoa.AtSync -analyzer-store=region -Wno-pointer-to-int-cast -verify -fblocks -Wno-unreachable-code -Wno-null-dereference -Wno-objc-root-class %s #ifndef __clang_analyzer__ #error __clang_analyzer__ not defined diff --git a/clang/test/Analysis/ptr-arith.c b/clang/test/Analysis/ptr-arith.c --- a/clang/test/Analysis/ptr-arith.c +++ b/clang/test/Analysis/ptr-arith.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -verify -triple x86_64-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,debug.ExprInspection -analyzer-store=region -Wno-pointer-to-int-cast -verify -triple i686-apple-darwin9 -Wno-tautological-pointer-compare -analyzer-config eagerly-assume=false %s void clang_analyzer_eval(int); diff --git a/clang/test/Analysis/svalbuilder-logic.c b/clang/test/Analysis/svalbuilder-logic.c --- a/clang/test/Analysis/svalbuilder-logic.c +++ b/clang/test/Analysis/svalbuilder-logic.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -Wno-pointer-to-int-cast -verify %s // expected-no-diagnostics // Testing core functionality of the SValBuilder. diff --git a/clang/test/Analysis/symbol-reaper.c b/clang/test/Analysis/symbol-reaper.c --- a/clang/test/Analysis/symbol-reaper.c +++ b/clang/test/Analysis/symbol-reaper.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -Wno-pointer-to-int-cast -verify %s void clang_analyzer_eval(int); void clang_analyzer_warnOnDeadSymbol(int); diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-pc-linux-gnu -ffreestanding -verify -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-pc-linux-gnu -ffreestanding -Wno-pointer-to-int-cast -verify -emit-llvm -o - %s | FileCheck %s #include diff --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c --- a/clang/test/Sema/MicrosoftExtensions.c +++ b/clang/test/Sema/MicrosoftExtensions.c @@ -92,18 +92,16 @@ SomeValue = 0x100000000 }; - void pointer_to_integral_type_conv(char* ptr) { - char ch = (char)ptr; - short sh = (short)ptr; - ch = (char)ptr; - sh = (short)ptr; + char ch = (char)ptr; // expected-warning{{cast to smaller integer type 'char' from 'char *' is a Microsoft extension}} + short sh = (short)ptr; // expected-warning{{cast to smaller integer type 'short' from 'char *' is a Microsoft extension}} + ch = (char)ptr; // expected-warning{{cast to smaller integer type 'char' from 'char *' is a Microsoft extension}} + sh = (short)ptr; // expected-warning{{cast to smaller integer type 'short' from 'char *' is a Microsoft extension}} // This is valid ISO C. - _Bool b = (_Bool)ptr; + _Bool b = (_Bool)ptr; // expected-warning{{cast to smaller integer type '_Bool' from 'char *' is a Microsoft extension}} } - typedef struct { UNKNOWN u; // expected-error {{unknown type name 'UNKNOWN'}} } AA; diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c --- a/clang/test/Sema/block-return.c +++ b/clang/test/Sema/block-return.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -Wno-int-to-pointer-cast -pedantic -fsyntax-only %s -verify -fblocks +// RUN: %clang_cc1 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -pedantic -fsyntax-only %s -verify -fblocks typedef void (^CL)(void); diff --git a/clang/test/Sema/cast.c b/clang/test/Sema/cast.c --- a/clang/test/Sema/cast.c +++ b/clang/test/Sema/cast.c @@ -151,19 +151,31 @@ } void testVoidPtr(VoidPtr v) { - (void) (Bool) v; - (void) (Int) v; + (void) (Bool) v; // expected-warning{{cast to smaller integer type 'Bool' (aka '_Bool') from 'VoidPtr' (aka 'void *')}} + (void) (Int) v; // expected-warning{{cast to smaller integer type 'Int' (aka 'int') from 'VoidPtr' (aka 'void *')}} (void) (Long) v; (void) (VoidPtr) v; (void) (CharPtr) v; + // Test that casts to void* can be controlled separately + // from other -Wpointer-to-int-cast warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvoid-pointer-to-int-cast" + (void) (Bool) v; // no-warning +#pragma clang diagnostic pop } void testCharPtr(CharPtr v) { - (void) (Bool) v; - (void) (Int) v; + (void) (Bool) v; // expected-warning{{cast to smaller integer type 'Bool' (aka '_Bool') from 'CharPtr' (aka 'char *')}} + (void) (Int) v; // expected-warning{{cast to smaller integer type 'Int' (aka 'int') from 'CharPtr' (aka 'char *')}} (void) (Long) v; (void) (VoidPtr) v; (void) (CharPtr) v; + // Test that casts to void* can be controlled separately + // from other -Wpointer-to-int-cast warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvoid-pointer-to-int-cast" + (void) (Bool) v; // expected-warning{{cast to smaller integer type 'Bool' (aka '_Bool') from 'CharPtr' (aka 'char *')}} +#pragma clang diagnostic pop } typedef enum { x_a, x_b } X; diff --git a/clang/test/Sema/const-eval.c b/clang/test/Sema/const-eval.c --- a/clang/test/Sema/const-eval.c +++ b/clang/test/Sema/const-eval.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux %s -Wno-tautological-pointer-compare +// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast #define EVAL_EXPR(testno, expr) int test##testno = sizeof(struct{char qq[expr];}); int x; diff --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c --- a/clang/test/Sema/init.c +++ b/clang/test/Sema/init.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only -ffreestanding +// RUN: %clang_cc1 %s -Wno-pointer-to-int-cast -verify -fsyntax-only -ffreestanding #include #include diff --git a/clang/test/Sema/offsetof.c b/clang/test/Sema/offsetof.c --- a/clang/test/Sema/offsetof.c +++ b/clang/test/Sema/offsetof.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wno-pointer-to-int-cast -fsyntax-only -verify %s #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) diff --git a/clang/test/Sema/static-init.c b/clang/test/Sema/static-init.c --- a/clang/test/Sema/static-init.c +++ b/clang/test/Sema/static-init.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wno-bool-conversion %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-pointer-to-int-cast -Wno-bool-conversion %s typedef __typeof((int*) 0 - (int*) 0) intptr_t; diff --git a/clang/test/Sema/struct-decl.c b/clang/test/Sema/struct-decl.c --- a/clang/test/Sema/struct-decl.c +++ b/clang/test/Sema/struct-decl.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wno-pointer-to-int-cast -fsyntax-only -verify %s // PR3459 struct bar { char n[1]; diff --git a/clang/test/SemaObjC/arc.m b/clang/test/SemaObjC/arc.m --- a/clang/test/SemaObjC/arc.m +++ b/clang/test/SemaObjC/arc.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-objc-root-class %s -// RUN: not %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -Wno-objc-root-class -fdiagnostics-parseable-fixits %s 2>&1 +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -verify -Wno-pointer-to-int-cast -Wno-objc-root-class %s +// RUN: not %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -fblocks -Wno-pointer-to-int-cast -Wno-objc-root-class -fdiagnostics-parseable-fixits %s 2>&1 typedef unsigned long NSUInteger; typedef const void * CFTypeRef; diff --git a/clang/test/SemaObjC/gcc-cast-ext.m b/clang/test/SemaObjC/gcc-cast-ext.m --- a/clang/test/SemaObjC/gcc-cast-ext.m +++ b/clang/test/SemaObjC/gcc-cast-ext.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -fms-extensions -Wno-objc-root-class %s +// RUN: %clang_cc1 -verify -Wno-pointer-to-int-cast -Wno-objc-root-class %s @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; typedef struct _NSRange { } NSRange; diff --git a/clang/test/SemaObjC/protocol-archane.m b/clang/test/SemaObjC/protocol-archane.m --- a/clang/test/SemaObjC/protocol-archane.m +++ b/clang/test/SemaObjC/protocol-archane.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-pointer-to-int-cast -Wno-objc-root-class %s // rdar://5986251 @protocol SomeProtocol