diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-08-23 03:24:04 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-08-23 03:24:04 +0000 |
commit | 85f7294e5af0cb7ea8e2d0469b96d0369627c48c (patch) | |
tree | 660d5bfec2c4faa55fa34797a9547b871dbb80ab /clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp | |
parent | 62a76d0ae349f53d4ebd911412591ec1bb74f4e7 (diff) | |
download | bcm5719-llvm-85f7294e5af0cb7ea8e2d0469b96d0369627c48c.tar.gz bcm5719-llvm-85f7294e5af0cb7ea8e2d0469b96d0369627c48c.zip |
[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.
llvm-svn: 369729
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp index a0cebd6ab85..cc1c9a66b90 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp @@ -138,6 +138,20 @@ static const NoteTag *getNoteTag(CheckerContext &C, // 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 CallEvent &Call, DefinedOrUnknownSVal DV, } 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 CallEvent &Call, DefinedOrUnknownSVal DV, 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(const CallEvent &Call, 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; |