blob: bd1329539d22754e168b01cec349b52cceae9f67 [file] [log] [blame]
commit 9830901b341cfb884cdef00e0335c6e3e62d107a
Author: Christopher Di Bella <cjdb@google.com>
Date: Fri Feb 26 00:11:25 2021 +0000
[clang] removes check against integral-to-pointer conversion...
... unless it's a literal
D94640 was a bit too aggressive in its analysis, considering integers
representing valid addresses as invalid. This change rolls back some of
the check, so that only the most obvious case is still flagged.
Before:
```cpp
free((void*)1000); // literal converted to `void*`: warning good
free((void*)an_int); // `int` object converted to `void*`: warning might
// be a false positive
```
After
```cpp
free((void*)1000); // literal converted to `void*`: warning good
free((void*)an_int); // doesn't warn
```
Differential Revision: https://reviews.llvm.org/D97512
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7e6dd354caac..22dd634c5031 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -10316,11 +10316,18 @@ void CheckFreeArgumentsCast(Sema &S, const std::string &CalleeName,
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<IntegerLiteral>(
+ 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
index 84d53472158c..59767b5917d7 100644
--- a/clang/test/Analysis/free.c
+++ b/clang/test/Analysis/free.c
@@ -108,3 +108,11 @@ void t17(void) {
// 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
index 2559770d6ddb..85b0935a5199 100644
--- a/clang/test/Analysis/free.cpp
+++ b/clang/test/Analysis/free.cpp
@@ -208,3 +208,39 @@ void t17b (char **x, int offset) {
// 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<unsigned long long>(s.p)); // no warning
+}
+
+void t18_C_style_reinterpret_std_free (S s) {
+ std::free((void*)reinterpret_cast<unsigned long long>(s.p)); // no warning
+}
+
+void t18_reinterpret_C_style_free (S s) {
+ free(reinterpret_cast<void*>((unsigned long long)(s.p))); // no warning
+}
+
+void t18_reinterpret_C_style_std_free (S s) {
+ std::free(reinterpret_cast<void*>((unsigned long long)(s.p))); // no warning
+}
+
+void t18_reinterpret_reinterpret_free (S s) {
+ free(reinterpret_cast<void*>(reinterpret_cast<unsigned long long>(s.p))); // no warning
+}
+
+void t18_reinterpret_reinterpret_std_free (S s) {
+ std::free(reinterpret_cast<void*>(reinterpret_cast<unsigned long long>(s.p))); // no warning
+}