r369729 - [analyzer] CastValueChecker: Correctly model results of based-to-derived casts.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 22 20:24:04 PDT 2019
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 at -1 {{'S' is a 'Circle'}}
- // expected-note at -2 {{'C' initialized here}}
+ // expected-note at -1 {{'C' initialized here}}
(void)(1 / !C);
// expected-note at -1 {{'C' is non-null}}
More information about the cfe-commits
mailing list