diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10316,11 +10316,18 @@ const CastExpr *Cast) { SmallString<128> SizeString; llvm::raw_svector_ostream OS(SizeString); + + clang::CastKind Kind = Cast->getCastKind(); + if (Kind == clang::CK_BitCast && + !Cast->getSubExpr()->getType()->isFunctionPointerType()) + return; + if (Kind == clang::CK_IntegralToPointer && + !isa( + Cast->getSubExpr()->IgnoreParenImpCasts()->IgnoreParens())) + return; + switch (Cast->getCastKind()) { case clang::CK_BitCast: - if (!Cast->getSubExpr()->getType()->isFunctionPointerType()) - return; - LLVM_FALLTHROUGH; case clang::CK_IntegralToPointer: case clang::CK_FunctionToPointerDecay: OS << '\''; diff --git a/clang/test/Analysis/free.c b/clang/test/Analysis/free.c --- a/clang/test/Analysis/free.c +++ b/clang/test/Analysis/free.c @@ -108,3 +108,11 @@ // expected-warning@-1{{Argument to free() is the address of the function 'iptr', which is not memory allocated by malloc()}} // expected-warning@-2{{attempt to call free on non-heap object 'iptr'}} } + +struct S { + const char* p; +}; + +void t18 (struct S s) { + free((void*)(unsigned long long)s.p); // no warning +} diff --git a/clang/test/Analysis/free.cpp b/clang/test/Analysis/free.cpp --- a/clang/test/Analysis/free.cpp +++ b/clang/test/Analysis/free.cpp @@ -208,3 +208,39 @@ // Unknown value std::free(x[offset]); // no-warning } + +struct S { + const char* p; +}; + +void t18_C_style_C_style_free (S s) { + free((void*)(unsigned long long)s.p); // no warning +} + +void t18_C_style_C_style_std_free (S s) { + std::free((void*)(unsigned long long)s.p); // no warning +} + +void t18_C_style_reinterpret_free (S s) { + free((void*)reinterpret_cast(s.p)); // no warning +} + +void t18_C_style_reinterpret_std_free (S s) { + std::free((void*)reinterpret_cast(s.p)); // no warning +} + +void t18_reinterpret_C_style_free (S s) { + free(reinterpret_cast((unsigned long long)(s.p))); // no warning +} + +void t18_reinterpret_C_style_std_free (S s) { + std::free(reinterpret_cast((unsigned long long)(s.p))); // no warning +} + +void t18_reinterpret_reinterpret_free (S s) { + free(reinterpret_cast(reinterpret_cast(s.p))); // no warning +} + +void t18_reinterpret_reinterpret_std_free (S s) { + std::free(reinterpret_cast(reinterpret_cast(s.p))); // no warning +}