Author: dergachev Date: Thu Aug 22 20:23:58 2019 New Revision: 369727 URL: http://llvm.org/viewvc/llvm-project?rev=369727&view=rev Log: [analyzer] CastValueChecker: Avoid modeling casts between objects.
Our method only works correctly when casting a pointer to a pointer or a reference to a reference. Fixes a crash. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp cfe/trunk/test/Analysis/Inputs/llvm.h cfe/trunk/test/Analysis/cast-value-logic.cpp cfe/trunk/test/Analysis/cast-value-notes.cpp cfe/trunk/test/Analysis/cast-value-state-dump.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp?rev=369727&r1=369726&r2=369727&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp Thu Aug 22 20:23:58 2019 @@ -382,8 +382,13 @@ bool CastValueChecker::evalCall(const Ca 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>(); Modified: cfe/trunk/test/Analysis/Inputs/llvm.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/llvm.h?rev=369727&r1=369726&r2=369727&view=diff ============================================================================== --- cfe/trunk/test/Analysis/Inputs/llvm.h (original) +++ cfe/trunk/test/Analysis/Inputs/llvm.h Thu Aug 22 20:23:58 2019 @@ -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 Modified: cfe/trunk/test/Analysis/cast-value-logic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cast-value-logic.cpp?rev=369727&r1=369726&r2=369727&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cast-value-logic.cpp (original) +++ cfe/trunk/test/Analysis/cast-value-logic.cpp Thu Aug 22 20:23:58 2019 @@ -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 Modified: cfe/trunk/test/Analysis/cast-value-notes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cast-value-notes.cpp?rev=369727&r1=369726&r2=369727&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cast-value-notes.cpp (original) +++ cfe/trunk/test/Analysis/cast-value-notes.cpp Thu Aug 22 20:23:58 2019 @@ -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 Sh // 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'}} Modified: cfe/trunk/test/Analysis/cast-value-state-dump.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cast-value-state-dump.cpp?rev=369727&r1=369726&r2=369727&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cast-value-state-dump.cpp (original) +++ cfe/trunk/test/Analysis/cast-value-state-dump.cpp Thu Aug 22 20:23:58 2019 @@ -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 evalNonNullParamNonNullReturnRefere 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: ]} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits