summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp9
-rw-r--r--clang/test/Analysis/Inputs/llvm.h5
-rw-r--r--clang/test/Analysis/cast-value-logic.cpp6
-rw-r--r--clang/test/Analysis/cast-value-notes.cpp11
-rw-r--r--clang/test/Analysis/cast-value-state-dump.cpp6
5 files changed, 27 insertions, 10 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
index 8724e4acbc4..cd3b70db9a5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
@@ -382,8 +382,13 @@ bool CastValueChecker::evalCall(const CallEvent &Call,
switch (Kind) {
case CallKind::Function: {
- // We need to obtain the record type of the call's parameter to model it.
- if (!getRecordType(Call.parameters()[0]->getType())->isRecordType())
+ // We only model casts from pointers to pointers or from references
+ // to references. Other casts are most likely specialized and we
+ // cannot model them.
+ QualType ParamT = Call.parameters()[0]->getType();
+ QualType ResultT = Call.getResultType();
+ if (!(ParamT->isPointerType() && ResultT->isPointerType()) &&
+ !(ParamT->isReferenceType() && ResultT->isReferenceType()))
return false;
DV = Call.getArgSVal(0).getAs<DefinedOrUnknownSVal>();
diff --git a/clang/test/Analysis/Inputs/llvm.h b/clang/test/Analysis/Inputs/llvm.h
index d77b4648107..c9d66ba2374 100644
--- a/clang/test/Analysis/Inputs/llvm.h
+++ b/clang/test/Analysis/Inputs/llvm.h
@@ -1,5 +1,7 @@
#pragma clang system_header
+#include "system-header-simulator-cxx.h"
+
namespace llvm {
template <class X, class Y>
const X *cast(Y Value);
@@ -22,4 +24,7 @@ bool isa(Y Value);
template <class X, class Y>
bool isa_and_nonnull(Y Value);
+
+template <typename X, typename Y>
+std::unique_ptr<X> cast(std::unique_ptr<Y> &&Value);
} // namespace llvm
diff --git a/clang/test/Analysis/cast-value-logic.cpp b/clang/test/Analysis/cast-value-logic.cpp
index 0d2255a3aba..c5083ef57c9 100644
--- a/clang/test/Analysis/cast-value-logic.cpp
+++ b/clang/test/Analysis/cast-value-logic.cpp
@@ -135,4 +135,10 @@ namespace crashes {
void test_non_reference_null_region_crash(Shape s) {
cast<Circle>(s); // no-crash
}
+
+void test_non_reference_temporary_crash() {
+ extern std::unique_ptr<Shape> foo();
+ auto P = foo();
+ auto Q = cast<Circle>(std::move(P)); // no-crash
+}
} // namespace crashes
diff --git a/clang/test/Analysis/cast-value-notes.cpp b/clang/test/Analysis/cast-value-notes.cpp
index 6e7f6b01af7..f92ba90336a 100644
--- a/clang/test/Analysis/cast-value-notes.cpp
+++ b/clang/test/Analysis/cast-value-notes.cpp
@@ -27,9 +27,9 @@ void evalReferences(const Shape &S) {
}
void evalNonNullParamNonNullReturnReference(const Shape &S) {
+ // Unmodeled cast from reference to pointer.
const auto *C = dyn_cast_or_null<Circle>(S);
- // expected-note@-1 {{Assuming 'S' is a 'Circle'}}
- // expected-note@-2 {{'C' initialized here}}
+ // expected-note@-1 {{'C' initialized here}}
if (!dyn_cast_or_null<Circle>(C)) {
// expected-note@-1 {{'C' is a 'Circle'}}
@@ -132,10 +132,11 @@ void evalZeroParamNonNullReturn(const Shape &S) {
// expected-warning@-3 {{Division by zero}}
}
-void evalZeroParamNullReturn(const Shape &S) {
- const auto *C = S.getAs<Circle>();
+void evalZeroParamNullReturn(const Shape *S) {
+ const auto &C = S->getAs<Circle>();
// expected-note@-1 {{Assuming 'S' is not a 'Circle'}}
- // expected-note@-2 {{'C' initialized to a null pointer value}}
+ // expected-note@-2 {{Storing null pointer value}}
+ // expected-note@-3 {{'C' initialized here}}
if (!dyn_cast_or_null<Triangle>(S)) {
// expected-note@-1 {{Assuming 'S' is a 'Triangle'}}
diff --git a/clang/test/Analysis/cast-value-state-dump.cpp b/clang/test/Analysis/cast-value-state-dump.cpp
index fd679984d6b..890fa189335 100644
--- a/clang/test/Analysis/cast-value-state-dump.cpp
+++ b/clang/test/Analysis/cast-value-state-dump.cpp
@@ -16,7 +16,7 @@ class Square : public Shape {};
using namespace llvm;
using namespace clang;
-void evalNonNullParamNonNullReturnReference(const Shape &S) {
+void evalNonNullParamNonNullReturn(const Shape *S) {
const auto *C = dyn_cast_or_null<Circle>(S);
// expected-note@-1 {{Assuming 'S' is a 'Circle'}}
// expected-note@-2 {{'C' initialized here}}
@@ -31,10 +31,10 @@ void evalNonNullParamNonNullReturnReference(const Shape &S) {
clang_analyzer_printState();
// CHECK: "dynamic_types": [
- // CHECK-NEXT: { "region": "SymRegion{reg_$0<const struct clang::Shape & S>}", "dyn_type": "const class clang::Circle", "sub_classable": true }
+ // CHECK-NEXT: { "region": "SymRegion{reg_$0<const struct clang::Shape * S>}", "dyn_type": "const class clang::Circle", "sub_classable": true }
// CHECK-NEXT: ],
// CHECK-NEXT: "dynamic_casts": [
- // CHECK: { "region": "SymRegion{reg_$0<const struct clang::Shape & S>}", "casts": [
+ // CHECK: { "region": "SymRegion{reg_$0<const struct clang::Shape * S>}", "casts": [
// CHECK-NEXT: { "from": "struct clang::Shape", "to": "class clang::Circle", "kind": "success" },
// CHECK-NEXT: { "from": "struct clang::Shape", "to": "class clang::Square", "kind": "fail" }
// CHECK-NEXT: ]}
OpenPOWER on IntegriCloud