summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2012-10-16 18:53:14 +0000
committerDavid Blaikie <dblaikie@gmail.com>2012-10-16 18:53:14 +0000
commit282ad876bd89a7d7ce698ab4128dc8f0a18105cd (patch)
tree5dad6bf2a61d47ad89b5586d5f6b67bb3e02efcd
parent794baf6fb7ac22fb4e4954f33f16886a5ab2a540 (diff)
downloadbcm5719-llvm-282ad876bd89a7d7ce698ab4128dc8f0a18105cd.tar.gz
bcm5719-llvm-282ad876bd89a7d7ce698ab4128dc8f0a18105cd.zip
Implement GCC's -Wint-to-pointer-cast.
This implementation doesn't warn on anything that GCC doesn't warn on with the exception of templates specializations (GCC doesn't warn, Clang does). The specific skipped cases (boolean, constant expressions, enums) are open for debate/adjustment if anyone wants to demonstrate that GCC is being overly conservative here. The only really obvious false positive I found was in the Clang regression suite's MPI test - apparently MPI uses specific flag values in pointer constants. (eg: #define FOO (void*)~0) llvm-svn: 166039
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td4
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/lib/Sema/SemaCast.cpp20
-rw-r--r--clang/test/Analysis/CFContainers.mm2
-rw-r--r--clang/test/Analysis/idempotent-operations.c2
-rw-r--r--clang/test/Analysis/misc-ps-region-store.m3
-rw-r--r--clang/test/Analysis/taint-tester.c2
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp6
-rw-r--r--clang/test/Sema/block-return.c2
-rw-r--r--clang/test/Sema/cast.c15
-rw-r--r--clang/test/Sema/i-c-e.c2
-rw-r--r--clang/test/SemaCXX/cast-conversion.cpp22
-rw-r--r--clang/test/SemaCXX/decl-expr-ambiguity.cpp2
13 files changed, 72 insertions, 14 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 4b0f4f13c0d..7951e35778a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -365,6 +365,8 @@ def Format2 : DiagGroup<"format=2",
def TypeSafety : DiagGroup<"type-safety">;
+def IntToPointerCast : DiagGroup<"int-to-pointer-cast">;
+
def Extra : DiagGroup<"extra", [
MissingFieldInitializers,
IgnoredQualifiers,
@@ -412,7 +414,7 @@ def ThreadSafety : DiagGroup<"thread-safety",
// Note that putting warnings in -Wall will not disable them by default. If a
// warning should be active _only_ when -Wall is passed in, mark it as
// DefaultIgnore in addition to putting it here.
-def : DiagGroup<"all", [Most, Parentheses, Switch]>;
+def : DiagGroup<"all", [Most, Parentheses, Switch, IntToPointerCast]>;
// Warnings enabled by -pedantic. This is magically filled in by TableGen.
def Pedantic : DiagGroup<"pedantic">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 953aab6983f..8389e4e10fa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1995,6 +1995,10 @@ def warn_cast_align : Warning<
"cast from %0 to %1 increases required alignment from %2 to %3">,
InGroup<CastAlign>, DefaultIgnore;
+def warn_int_to_pointer_cast : Warning<
+ "cast to %1 from smaller integer type %0">,
+ InGroup<IntToPointerCast>;
+
def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">,
InGroup<IgnoredAttributes>;
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 0c3757821eb..bf25c617854 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1491,6 +1491,22 @@ static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr,
}
}
+static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
+ const Expr *SrcExpr, QualType DestType,
+ Sema &Self) {
+ QualType SrcType = SrcExpr->getType();
+
+ // Not warning on reinterpret_cast, boolean, constant expressions, etc
+ // are not explicit design choices, but consistent with GCC's behavior.
+ // Feel free to modify them if you've reason/evidence for an alternative.
+ if (CStyle && SrcType->isIntegralType(Self.Context)
+ && !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;
+}
+
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
@@ -1689,6 +1705,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
if (SrcType->isIntegralOrEnumerationType()) {
assert(destIsPtr && "One type must be a pointer");
+ checkIntToPointerCast(CStyle, OpRange.getBegin(), 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
@@ -2071,6 +2089,8 @@ void CastOperation::CheckCStyleCast() {
SrcExpr = ExprError();
return;
}
+ checkIntToPointerCast(/* CStyle */ true, OpRange.getBegin(), SrcExpr.get(),
+ DestType, Self);
} else if (!SrcType->isArithmeticType()) {
if (!DestType->isIntegralType(Self.Context) &&
DestType->isArithmeticType()) {
diff --git a/clang/test/Analysis/CFContainers.mm b/clang/test/Analysis/CFContainers.mm
index e1431df47a0..b01942310f7 100644
--- a/clang/test/Analysis/CFContainers.mm
+++ b/clang/test/Analysis/CFContainers.mm
@@ -125,7 +125,7 @@ void CreateDict(int *elems) {
const CFDictionaryKeyCallBacks keyCB = kCFCopyStringDictionaryKeyCallBacks;
const CFDictionaryValueCallBacks valCB = kCFTypeDictionaryValueCallBacks;
CFDictionaryRef dict1 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, numValues, &keyCB, &valCB); // no warning
- CFDictionaryRef dict2 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)elems[0], (const void**)values, numValues, &keyCB, &valCB); //expected-warning {{The second argument to 'CFDictionaryCreate' must be a C array of}}
+ CFDictionaryRef dict2 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)elems[0], (const void**)values, numValues, &keyCB, &valCB); //expected-warning {{The second argument to 'CFDictionaryCreate' must be a C array of}} expected-warning {{cast to 'const void **' from smaller integer type 'int'}}
CFDictionaryRef dict3 = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)elems, numValues, &keyCB, &valCB); // expected-warning {{The third argument to 'CFDictionaryCreate' must be a C array of pointer-sized values}}
}
diff --git a/clang/test/Analysis/idempotent-operations.c b/clang/test/Analysis/idempotent-operations.c
index 793e7cd324b..04c9bc1893e 100644
--- a/clang/test/Analysis/idempotent-operations.c
+++ b/clang/test/Analysis/idempotent-operations.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-checker=alpha.deadcode.IdempotentOperations -verify %s
+// RUN: %clang_cc1 -Wno-int-to-pointer-cast -analyze -analyzer-store=region -analyzer-constraints=range -fblocks -analyzer-opt-analyze-nested-blocks -analyzer-checker=alpha.deadcode.IdempotentOperations -verify %s
// Basic tests
diff --git a/clang/test/Analysis/misc-ps-region-store.m b/clang/test/Analysis/misc-ps-region-store.m
index 800a008d17c..f772894ff82 100644
--- a/clang/test/Analysis/misc-ps-region-store.m
+++ b/clang/test/Analysis/misc-ps-region-store.m
@@ -1086,6 +1086,9 @@ pr8052(u_int boot_addr)
u_char *src = (u_char *) ((u_long) bootMP);
u_char *dst = (u_char *) boot_addr + ((vm_offset_t) ((((((((1 <<
12) / (sizeof(pd_entry_t))) - 1) - 1) - (260 - 2))) << 22) | ((0) << 12)));
+#ifdef TEST_64
+// expected-warning@-3 {{cast to 'u_char *' (aka 'unsigned char *') from smaller integer type 'u_int' (aka 'unsigned int')}}
+#endif
for (x = 0;
x < size;
++x)
diff --git a/clang/test/Analysis/taint-tester.c b/clang/test/Analysis/taint-tester.c
index 67383accb2a..7b0ab2a5fd3 100644
--- a/clang/test/Analysis/taint-tester.c
+++ b/clang/test/Analysis/taint-tester.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.security.taint,debug.TaintTest %s -verify
+// RUN: %clang_cc1 -Wno-int-to-pointer-cast -analyze -analyzer-checker=alpha.security.taint,debug.TaintTest %s -verify
#include <stdarg.h>
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
index fd17d35677d..3c1152c631b 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fcxx-exceptions %s
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -verify -std=c++11 -fcxx-exceptions %s
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -std=c++11 -fcxx-exceptions -Wno-invalid-constexpr %s
namespace StdExample {
@@ -80,7 +80,7 @@ constexpr int Conditional2(bool b, int n) { return b ? n * ng : n + ng; } // exp
// __builtin_constant_p ? : is magical, and is always a potential constant.
constexpr bool BcpCall(int n) {
- return __builtin_constant_p((int*)n != &n) ? (int*)n != &n : (int*)n != &n;
+ return __builtin_constant_p((int*)n != &n) ? (int*)n != &n : (int*)n != &n; // expected-warning 3 {{cast to 'int *' from smaller integer type 'int'}}
}
static_assert(BcpCall(0), "");
diff --git a/clang/test/Sema/block-return.c b/clang/test/Sema/block-return.c
index 6967955b087..2ea4d813ab0 100644
--- a/clang/test/Sema/block-return.c
+++ b/clang/test/Sema/block-return.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -pedantic -fsyntax-only %s -verify -fblocks
+// RUN: %clang_cc1 -Wno-int-to-pointer-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
index 71c44b4b816..25ef1d03a4f 100644
--- a/clang/test/Sema/cast.c
+++ b/clang/test/Sema/cast.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only %s -verify
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown %s -verify
typedef struct { unsigned long bits[(((1) + (64) - 1) / (64))]; } cpumask_t;
cpumask_t x;
@@ -52,8 +52,8 @@ void testInt(Int v) {
(void) (CLong) v;
(void) (CFloat) v;
(void) (CDouble) v;
- (void) (VoidPtr) v;
- (void) (CharPtr) 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')}}
}
void testLong(Long v) {
@@ -157,3 +157,12 @@ void testCharPtr(CharPtr v) {
(void) (VoidPtr) v;
(void) (CharPtr) v;
}
+
+typedef enum { x_a, x_b } X;
+void *intToPointerCast2(X x) {
+ return (void*)x;
+}
+
+void *intToPointerCast3() {
+ return (void*)(1 + 3);
+}
diff --git a/clang/test/Sema/i-c-e.c b/clang/test/Sema/i-c-e.c
index ee61ac34a81..e7b42c4e9a1 100644
--- a/clang/test/Sema/i-c-e.c
+++ b/clang/test/Sema/i-c-e.c
@@ -1,4 +1,4 @@
-// RUN: %clang %s -ffreestanding -fsyntax-only -Xclang -verify -pedantic -fpascal-strings -std=c99
+// RUN: %clang %s -ffreestanding -Wno-int-to-pointer-cast -fsyntax-only -Xclang -verify -pedantic -fpascal-strings -std=c99
#include <stdint.h>
#include <limits.h>
diff --git a/clang/test/SemaCXX/cast-conversion.cpp b/clang/test/SemaCXX/cast-conversion.cpp
index dd2bc98e02c..270f96831bd 100644
--- a/clang/test/SemaCXX/cast-conversion.cpp
+++ b/clang/test/SemaCXX/cast-conversion.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown -verify %s -std=c++11
struct R {
R(int);
@@ -45,3 +45,23 @@ protected:
static_cast<float*>(f0<0>()); // expected-error{{ambiguous}}
}
};
+
+void *intToPointer1(short s) {
+ return (void*)s; // expected-warning{{cast to 'void *' from smaller integer type 'short'}}
+}
+
+void *intToPointer2(short s) {
+ return reinterpret_cast<void*>(s);
+}
+
+void *intToPointer3(bool b) {
+ return (void*)b;
+}
+
+void *intToPointer4() {
+ return (void*)(3 + 7);
+}
+
+void *intToPointer5(long l) {
+ return (void*)l;
+}
diff --git a/clang/test/SemaCXX/decl-expr-ambiguity.cpp b/clang/test/SemaCXX/decl-expr-ambiguity.cpp
index 0980c40cbfd..87fd2dad316 100644
--- a/clang/test/SemaCXX/decl-expr-ambiguity.cpp
+++ b/clang/test/SemaCXX/decl-expr-ambiguity.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -pedantic-errors %s
+// RUN: %clang_cc1 -Wno-int-to-pointer-cast -fsyntax-only -verify -pedantic-errors %s
void f() {
int a;
OpenPOWER on IntegriCloud