[Sema] Adds the pointer-to-int-cast diagnostic
Converting a pointer to an integer whose result cannot represented in the integer type is undefined behavior is C and prohibited in C++. C++ already has a diagnostic when casting. This adds a diagnostic for C. Since this diagnostic uses the range of the conversion it also modifies int-to-pointer-cast diagnostic to use a range. Fixes PR8718: No warning on casting between pointer and non-pointer-sized int Differential Revision: https://reviews.llvm.org/D72231
This commit is contained in:
@@ -51,7 +51,8 @@ Major New Features
|
||||
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
|
||||
-------------------------------------------------
|
||||
|
||||
@@ -836,6 +836,9 @@ def IncompatibleExceptionSpec : DiagGroup<"incompatible-exception-spec">;
|
||||
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,
|
||||
|
||||
@@ -3658,6 +3658,15 @@ def warn_int_to_pointer_cast : Warning<
|
||||
def warn_int_to_void_pointer_cast : Warning<
|
||||
"cast to %1 from smaller integer type %0">,
|
||||
InGroup<IntToVoidPointerCast>;
|
||||
def warn_pointer_to_int_cast : Warning<
|
||||
"cast to smaller integer type %1 from %0">,
|
||||
InGroup<PointerToIntCast>;
|
||||
def warn_void_pointer_to_int_cast : Warning<
|
||||
"cast to smaller integer type %1 from %0">,
|
||||
InGroup<VoidPointerToIntCast>;
|
||||
def ext_ms_pointer_to_int_cast : ExtWarn<
|
||||
"cast to smaller integer type %1 from %0 is a Microsoft extension">,
|
||||
InGroup<MicrosoftCast>;
|
||||
|
||||
def warn_attribute_ignored_for_field_of_type : Warning<
|
||||
"%0 attribute ignored for field of type %1">,
|
||||
|
||||
@@ -1961,7 +1961,7 @@ static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr,
|
||||
<< 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 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
|
||||
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 @@ 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);
|
||||
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 @@ void CastOperation::CheckCStyleCast() {
|
||||
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 @@ void CastOperation::CheckCStyleCast() {
|
||||
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 &&
|
||||
|
||||
@@ -523,6 +523,6 @@ struct S {
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
|
||||
@@ -92,18 +92,16 @@ enum : long long { // expected-warning{{enumeration types with a fixed underlyi
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -151,19 +151,31 @@ void testCDouble(CDouble v) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user