From: Ted Kremenek Date: Wed, 29 May 2013 21:50:46 +0000 (+0000) Subject: Split off casts to void* for -Wint-to-pointer-cast to subgroup -Wint-to-void-pointer... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2628b44e100da28972a14854f98d0aa6f7b888e0;p=clang Split off casts to void* for -Wint-to-pointer-cast to subgroup -Wint-to-void-pointer-cast. This change is motivated from user feedback that some APIs use void* as an opaque "context" object that may not really be a pointer. Such users want an ability to turn off the warning for casts to void* while preserving the warning for other cases. Implements . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182884 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 8c88a42fc2..565a01745f 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -416,7 +416,9 @@ def Format2 : DiagGroup<"format=2", def TypeSafety : DiagGroup<"type-safety">; -def IntToPointerCast : DiagGroup<"int-to-pointer-cast">; +def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">; +def IntToPointerCast : DiagGroup<"int-to-pointer-cast", + [IntToVoidPointerCast]>; def Extra : DiagGroup<"extra", [ MissingFieldInitializers, diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 28ca164ee8..46351da12f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2222,9 +2222,17 @@ def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, InGroup, DefaultIgnore; +// Separate between casts to void* and non-void* pointers. +// Some APIs use (abuse) void* for something like a user context, +// and often that value is an integer even if it isn't a pointer itself. +// Having a separate warning flag allows users to control the warning +// for their workflow. def warn_int_to_pointer_cast : Warning< "cast to %1 from smaller integer type %0">, InGroup; +def warn_int_to_void_pointer_cast : Warning< + "cast to %1 from smaller integer type %0">, + InGroup; def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">, diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index eb11a577cb..3f0a1a36e4 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -1614,8 +1614,18 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc, && !SrcType->isBooleanType() && !SrcType->isEnumeralType() && !SrcExpr->isIntegerConstantExpr(Self.Context) - && Self.Context.getTypeSize(DestType) > Self.Context.getTypeSize(SrcType)) - Self.Diag(Loc, diag::warn_int_to_pointer_cast) << SrcType << DestType; + && Self.Context.getTypeSize(DestType) > + Self.Context.getTypeSize(SrcType)) { + // Separate between casts to void* and non-void* pointers. + // Some APIs use (abuse) void* for something like a user context, + // and often that value is an integer even if it isn't a pointer itself. + // Having a separate warning flag allows users to control the warning + // for their workflow. + unsigned Diag = DestType->isVoidPointerType() ? + diag::warn_int_to_void_pointer_cast + : diag::warn_int_to_pointer_cast; + Self.Diag(Loc, Diag) << SrcType << DestType; + } } static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, diff --git a/test/Sema/cast.c b/test/Sema/cast.c index 25ef1d03a4..7971163c12 100644 --- a/test/Sema/cast.c +++ b/test/Sema/cast.c @@ -54,6 +54,14 @@ void testInt(Int v) { (void) (CDouble) v; (void) (VoidPtr) v; // expected-warning{{cast to 'VoidPtr' (aka 'void *') from smaller integer type 'Int' (aka 'int')}} (void) (CharPtr) v; // expected-warning{{cast to 'CharPtr' (aka 'char *') from smaller integer type 'Int' (aka 'int')}} + + // Test that casts to void* can be controlled separately + // from other -Wint-to-pointer-cast warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" + (void) (VoidPtr) v; // no-warning + (void) (CharPtr) v; // expected-warning{{cast to 'CharPtr' (aka 'char *') from smaller integer type 'Int' (aka 'int')}} +#pragma clang diagnostic pop } void testLong(Long v) {