Author: dergachev Date: Thu Aug 22 20:24:04 2019 New Revision: 369729 URL: http://llvm.org/viewvc/llvm-project?rev=369729&view=rev Log: [analyzer] CastValueChecker: Correctly model results of based-to-derived casts.
Our SVal hierarchy doesn't allow modeling pointer casts as no-op. The pointer type is instead encoded into the pointer object. Defer to our usual pointer casting facility, SValBuilder::evalBinOp(). Fixes a crash. Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp cfe/trunk/test/Analysis/cast-value-logic.cpp cfe/trunk/test/Analysis/cast-value-notes.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp?rev=369729&r1=369728&r2=369729&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp Thu Aug 22 20:24:04 2019 @@ -138,6 +138,20 @@ static const NoteTag *getNoteTag(Checker // Main logic to evaluate a cast. //===----------------------------------------------------------------------===// +static QualType alignReferenceTypes(QualType toAlign, QualType alignTowards, + ASTContext &ACtx) { + if (alignTowards->isLValueReferenceType() && + alignTowards.isConstQualified()) { + toAlign.addConst(); + return ACtx.getLValueReferenceType(toAlign); + } else if (alignTowards->isLValueReferenceType()) + return ACtx.getLValueReferenceType(toAlign); + else if (alignTowards->isRValueReferenceType()) + return ACtx.getRValueReferenceType(toAlign); + + llvm_unreachable("Must align towards a reference type!"); +} + static void addCastTransition(const CallEvent &Call, DefinedOrUnknownSVal DV, CheckerContext &C, bool IsNonNullParam, bool IsNonNullReturn, @@ -156,6 +170,15 @@ static void addCastTransition(const Call } else { Object = cast<CXXInstanceCall>(&Call)->getCXXThisExpr(); CastFromTy = Object->getType(); + if (CastToTy->isPointerType()) { + if (!CastFromTy->isPointerType()) + return; + } else { + if (!CastFromTy->isReferenceType()) + return; + + CastFromTy = alignReferenceTypes(CastFromTy, CastToTy, C.getASTContext()); + } } const MemRegion *MR = DV.getAsRegion(); @@ -183,7 +206,8 @@ static void addCastTransition(const Call State = setDynamicTypeAndCastInfo(State, MR, CastFromTy, CastToTy, CastSucceeds); - SVal V = CastSucceeds ? DV : C.getSValBuilder().makeNull(); + SVal V = CastSucceeds ? C.getSValBuilder().evalCast(DV, CastToTy, CastFromTy) + : C.getSValBuilder().makeNull(); C.addTransition( State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), V, false), getNoteTag(C, CastInfo, CastToTy, Object, CastSucceeds, IsKnownCast)); @@ -198,14 +222,8 @@ static void addInstanceOfTransition(cons QualType CastToTy = FD->getTemplateSpecializationArgs()->get(0).getAsType(); if (CastFromTy->isPointerType()) CastToTy = C.getASTContext().getPointerType(CastToTy); - else if (CastFromTy->isLValueReferenceType() && - CastFromTy.isConstQualified()) { - CastToTy.addConst(); - CastToTy = C.getASTContext().getLValueReferenceType(CastToTy); - } else if (CastFromTy->isLValueReferenceType()) - CastToTy = C.getASTContext().getLValueReferenceType(CastToTy); - else if (CastFromTy->isRValueReferenceType()) - CastToTy = C.getASTContext().getRValueReferenceType(CastToTy); + else if (CastFromTy->isReferenceType()) + CastToTy = alignReferenceTypes(CastToTy, CastFromTy, C.getASTContext()); else return; 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=369729&r1=369728&r2=369729&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cast-value-logic.cpp (original) +++ cfe/trunk/test/Analysis/cast-value-logic.cpp Thu Aug 22 20:24:04 2019 @@ -19,7 +19,11 @@ struct Shape { virtual double area(); }; class Triangle : public Shape {}; -class Circle : public Shape {}; +class Circle : public Shape { +public: + ~Circle(); +}; +class SuspiciouslySpecificCircle : public Circle {}; } // namespace clang using namespace llvm; @@ -149,4 +153,10 @@ double test_virtual_method_after_call(Sh return S->area(); return S->area() / 2; } + +void test_delete_crash() { + extern Circle *makeCircle(); + Shape *S = makeCircle(); + delete cast<SuspiciouslySpecificCircle>(S); +} } // 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=369729&r1=369728&r2=369729&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cast-value-notes.cpp (original) +++ cfe/trunk/test/Analysis/cast-value-notes.cpp Thu Aug 22 20:24:04 2019 @@ -123,8 +123,7 @@ void evalZeroParamNonNullReturnPointer(c void evalZeroParamNonNullReturn(const Shape &S) { const auto *C = S.castAs<Circle>(); - // expected-note@-1 {{'S' is a 'Circle'}} - // expected-note@-2 {{'C' initialized here}} + // expected-note@-1 {{'C' initialized here}} (void)(1 / !C); // expected-note@-1 {{'C' is non-null}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits