diff options
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 4 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | lib/Sema/SemaCast.cpp | 20 | ||||
-rw-r--r-- | test/Analysis/CFContainers.mm | 2 | ||||
-rw-r--r-- | test/Analysis/idempotent-operations.c | 2 | ||||
-rw-r--r-- | test/Analysis/misc-ps-region-store.m | 3 | ||||
-rw-r--r-- | test/Analysis/taint-tester.c | 2 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp | 6 | ||||
-rw-r--r-- | test/Sema/block-return.c | 2 | ||||
-rw-r--r-- | test/Sema/cast.c | 15 | ||||
-rw-r--r-- | test/Sema/i-c-e.c | 2 | ||||
-rw-r--r-- | test/SemaCXX/cast-conversion.cpp | 22 | ||||
-rw-r--r-- | test/SemaCXX/decl-expr-ambiguity.cpp | 2 |
13 files changed, 72 insertions, 14 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 4b0f4f13c0..7951e35778 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 953aab6983..8389e4e10f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 0c3757821e..bf25c61785 100644 --- a/lib/Sema/SemaCast.cpp +++ b/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/test/Analysis/CFContainers.mm b/test/Analysis/CFContainers.mm index e1431df47a..b01942310f 100644 --- a/test/Analysis/CFContainers.mm +++ b/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/test/Analysis/idempotent-operations.c b/test/Analysis/idempotent-operations.c index 793e7cd324..04c9bc1893 100644 --- a/test/Analysis/idempotent-operations.c +++ b/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/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 800a008d17..f772894ff8 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/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/test/Analysis/taint-tester.c b/test/Analysis/taint-tester.c index 67383accb2..7b0ab2a5fd 100644 --- a/test/Analysis/taint-tester.c +++ b/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/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp index fd17d35677..3c1152c631 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp +++ b/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/test/Sema/block-return.c b/test/Sema/block-return.c index 6967955b08..2ea4d813ab 100644 --- a/test/Sema/block-return.c +++ b/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/test/Sema/cast.c b/test/Sema/cast.c index 71c44b4b81..25ef1d03a4 100644 --- a/test/Sema/cast.c +++ b/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/test/Sema/i-c-e.c b/test/Sema/i-c-e.c index ee61ac34a8..e7b42c4e9a 100644 --- a/test/Sema/i-c-e.c +++ b/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/test/SemaCXX/cast-conversion.cpp b/test/SemaCXX/cast-conversion.cpp index dd2bc98e02..270f96831b 100644 --- a/test/SemaCXX/cast-conversion.cpp +++ b/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/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 0980c40cbf..87fd2dad31 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/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; |