]> granicus.if.org Git - clang/commitdiff
Split off casts to void* for -Wint-to-pointer-cast to subgroup -Wint-to-void-pointer...
authorTed Kremenek <kremenek@apple.com>
Wed, 29 May 2013 21:50:46 +0000 (21:50 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 29 May 2013 21:50:46 +0000 (21:50 +0000)
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 <rdar://problem/14016721>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182884 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaCast.cpp
test/Sema/cast.c

index 8c88a42fc2c5873b9fc9563384d51684e8780bf8..565a01745f11536b8a399df996aa291c796864a1 100644 (file)
@@ -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,
index 28ca164ee83a5647036c8dcaeb092f70e1a5368c..46351da12f2380098190e62bde4ebf92919caff5 100644 (file)
@@ -2222,9 +2222,17 @@ def warn_cast_align : Warning<
   "cast from %0 to %1 increases required alignment from %2 to %3">,
   InGroup<CastAlign>, 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<IntToPointerCast>;
+def warn_int_to_void_pointer_cast : Warning<
+  "cast to %1 from smaller integer type %0">,
+  InGroup<IntToVoidPointerCast>;
 
 def warn_attribute_ignored_for_field_of_type : Warning<
   "%0 attribute ignored for field of type %1">,
index eb11a577cb0ae79ea9d515504e31eb2b35499aab..3f0a1a36e46e2221826b486759c249aeff90a86c 100644 (file)
@@ -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,
index 25ef1d03a4fe7b6e47761783a33c8c721137b1b8..7971163c12d02c6a54ae3802b22a2642cb09a0c9 100644 (file)
@@ -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) {